Samchon Framework for CPP  1.0.0
SQLStatement.hpp
1 #pragma once
2 #include <samchon/API.hpp>
3 
4 #include <samchon/library/base/SQLiBase.hpp>
5 
6 #include <vector>
7 #include <memory>
8 #include <string>
9 
10 #include <samchon/ByteArray.hpp>
11 #include <samchon/HashMap.hpp>
12 #include <samchon/library/XML.hpp>
13 
14 namespace samchon
15 {
16 namespace library
17 {
18  class SQLi;
19 
47  {
48  friend class SQLi;
49  private:
50 #ifdef _WIN64
51  typedef long long SQL_SIZE_T;
52 #else
53  typedef long SQL_SIZE_T;
54 #endif
55 
56  protected:
57  /* --------------------------------------------------------------
58  BASIC MEMBER VARIABLES
59  -------------------------------------------------------------- */
64 
68  void *hstmt;
69 
70  /* --------------------------------------------------------------
71  MEMBER VARIABLES FOR BINDING
72  -------------------------------------------------------------- */
77 
85 
86  protected:
99  {
100  this->sqli = sqli;
101  bindParameterCount = 0;
102 
103  SQLAllocHandle(SQL_HANDLE_STMT, ((base::SQLiBase*)sqli)->hdbc, &hstmt);
104  };
105 
106  public:
107  virtual ~SQLStatement()
108  {
109  free();
110  };
111 
112  public:
113  void reset(SQLi *sqli)
114  {
115  free();
116  this->sqli = sqli;
117 
118  SQLAllocHandle(SQL_HANDLE_STMT, ((base::SQLiBase*)sqli)->hdbc, &hstmt);
119  };
120 
124  void free()
125  {
126  SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
127 
128  bindParameterCount = 0;
129 
130  if (sqli == nullptr || ((base::SQLiBase*)sqli)->stmt != this)
131  return;
132 
133  ((base::SQLiBase*)sqli)->stmt = nullptr;
134  ((base::SQLiBase*)sqli)->stmtMutex.unlock();
135  };
136 
140  void refresh()
141  {
142  reset(this->sqli);
143  };
144 
145  /* -----------------------------------------------------------------------
146  QUERY
147  ----------------------------------------------------------------------- */
148  void prepare(const std::string &sql)
149  {
150  refresh();
151 
152  ((base::SQLiBase*)sqli)->stmtMutex.lock();
153  ((base::SQLiBase*)sqli)->stmt = this;
154 
155  SQLPrepareA(hstmt, (SQLCHAR*)&sql[0], SQL_NTS);
156  };
157 
167  template <typename T, typename ... _Args>
168  void prepare(const std::string &sql, const T& val, const _Args& ... args)
169  {
170  prepare(sql);
171 
172  bindParameter(val);
173  bindParameter(args...);
174  };
175  template <typename T> void prepare(const std::string &str, const T& val)
176  {
177  prepare(str);
178 
179  bindParameter(val);
180  };
181 
182  void prepare(const std::wstring &sql)
183  {
184  refresh();
185 
186  ((base::SQLiBase*)sqli)->stmtMutex.lock();
187  ((base::SQLiBase*)sqli)->stmt = this;
188 
189  SQLPrepareW(hstmt, (SQLWCHAR*)&sql[0], SQL_NTS);
190  };
191 
192  template <typename T, typename ... _Args>
193  void prepare(const std::wstring &sql, const T& val, const _Args& ... args)
194  {
195  prepare(sql);
196 
197  bindParameter(val);
198  bindParameter(args...);
199  };
200  template <typename T> void prepare(const std::wstring &str, const T& val)
201  {
202  prepare(str);
203 
204  bindParameter(val);
205  };
206 
212  void execute()
213  {
214  SQLRETURN res = SQLExecute(hstmt);
215 
216  if (res == SQL_ERROR)
217  throw std::exception(((base::SQLiBase*)sqli)->getErrorMessage(SQL_HANDLE_STMT).data());
218 
219  // device or resource busy
220  // it means network disconnection in almost case
221  };
222 
239  void executeDirectly(const std::string &sql)
240  {
241  prepare(sql);
242  execute();
243  };
244  void executeDirectly(const std::wstring &sql)
245  {
246  prepare(sql);
247  execute();
248  };
249 
250  /* -----------------------------------------------------------------------
251  CURSOR
252  ----------------------------------------------------------------------- */
260  auto fetch() const -> bool
261  {
262  do
263  {
264  SQLSMALLINT colSize = 0;
265  SQLNumResultCols(hstmt, &colSize);
266 
267  if (colSize > 0)
268  break;
269  } while (next() == true);
270 
271  return (SQLFetch(hstmt) == SQL_SUCCESS);
272  };
273 
279  auto next() const -> bool
280  {
281  return (SQLMoreResults(hstmt) != SQL_NO_DATA);
282  };
283 
284  /* -------------------------------------------------------------------------
285  GET DATA IN A COLUMN
286  ------------------------------------------------------------------------- */
293  auto size() const -> size_t
294  {
295  SQLSMALLINT val = 0;
296 
297  SQLNumResultCols(hstmt, &val);
298  return (size_t)val;
299  };
300 
308  template <typename T> auto at(size_t index) const -> T
309  {
310  T val;
311  sql_get_data(index + 1, C_TYPE(T()), &val);
312 
313  return val;
314  };
315  template<> auto at(size_t index) const -> std::string
316  {
317  index++;
318 
319  std::string str(1, NULL);
320  SQLLEN size = 0;
321 
322  if (::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_CHAR, &str[0], 0, &size) != SQL_SUCCESS && size != 0)
323  {
324  // IMPORTANT, FOR NULL-TERMINATED-STRING
325  size++;
326 
327  str.assign(size, NULL);
328  ::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_CHAR, &str[0], sizeof(char)*size, NULL);
329  }
330 
331  // ERASE ZERO-CHARS
332  return str.data();
333  }
334  template<> auto at(size_t index) const -> std::wstring
335  {
336  index++;
337 
338  std::wstring str(1, NULL);
339  SQLLEN size = 0;
340 
341  if (::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_WCHAR, &str[0], 0, &size) != SQL_SUCCESS && size != 0)
342  {
343  // IMPORTANT, FOR NULL-TERMINATED-STRING
344  size++;
345 
346  str.assign((size_t)size, NULL);
347  ::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_WCHAR, &str[0], sizeof(wchar_t)*size, NULL);
348  }
349 
350  // ERASE ZERO-CHARS
351  return str.data();
352  };
353  template<> auto at(size_t index) const -> ByteArray
354  {
355  index++;
356 
357  ByteArray data;
358  SQLLEN size = 0;
359 
360  if (::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_BINARY, &data[0], 0, &size) != SQL_SUCCESS && size != 0)
361  {
362  data.assign(size, NULL);
363  ::SQLGetData(hstmt, (SQLUSMALLINT)index, SQL_C_BINARY, &data[0], data.size(), NULL);
364  }
365  return data;
366  };
367 
375  /*template <typename T> auto get(const std::string &) const -> T
376  {
377  return this->at<T>(0);
378  };*/
379 
389  //virtual auto toXML() const -> std::shared_ptr<XML>;
390 
391  private:
392  /* -------------------------------------------------------------------
393  BIND
394  ------------------------------------------------------------------- */
395  template <typename T, typename ... _Args>
396  void bindParameter(const T& val, const _Args& ... args)
397  {
398  bindParameter(val);
399  bindParameter(args...);
400  };
401  template <typename T> void bindParameter(const T &val)
402  {
403  sql_bind_parameter(C_TYPE(val), SQL_TYPE(val), (void*)&val);
404  };
405  template<> void bindParameter(const std::string &val)
406  {
407  ::SQLBindParameter(hstmt, (SQLUSMALLINT)++bindParameterCount, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, val.size(), 0, (SQLPOINTER)val.data(), val.size(), NULL);
408  };
409  template<> void bindParameter(const std::wstring &val)
410  {
411  ::SQLBindParameter(hstmt, (SQLUSMALLINT)++bindParameterCount, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WVARCHAR, val.size(), 0, (SQLPOINTER)val.data(), val.size(), NULL);
412  };
413  template<> void bindParameter(const ByteArray &val)
414  {
415  bindParameterBASizeMap.set(++bindParameterCount, (SQL_SIZE_T)val.size());
416 
417  ::SQLBindParameter(hstmt, (SQLUSMALLINT)bindParameterCount, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, val.size(), 0, (unsigned char*)&val[0], 0, &bindParameterBASizeMap.get(bindParameterCount));
418  };
419 
420  /* -------------------------------------------------------------------
421  ODBC'S FUNCTION
422  ------------------------------------------------------------------- */
423  void sql_get_data(size_t index, short type, void *listener) const
424  {
425  ::SQLGetData(hstmt, (SQLUSMALLINT)index, type, listener, 0, nullptr);
426  };
427  void sql_bind_parameter(short cppType, short sqlType, void *val)
428  {
429  ::SQLBindParameter(hstmt, (SQLUSMALLINT)++bindParameterCount, SQL_PARAM_INPUT, cppType, sqlType, 0, 0, val, 0, nullptr);
430  };
431 
432  template <typename T> auto C_TYPE(const T &) const -> short;
433  template<> auto C_TYPE(const bool &) const -> short
434  {
435  return SQL_C_BIT;
436  }
437  template<> auto C_TYPE(const char &) const -> short
438  {
439  return SQL_CHAR;
440  }
441  template<> auto C_TYPE(const short &) const -> short
442  {
443  return SQL_C_SSHORT;
444  }
445  template<> auto C_TYPE(const long &) const -> short
446  {
447  return SQL_C_SLONG;
448  }
449  template<> auto C_TYPE(const long long &) const -> short
450  {
451  return SQL_C_SBIGINT;
452  }
453  template<> auto C_TYPE(const int &) const -> short
454  {
455  return SQL_C_SLONG;
456  }
457  template<> auto C_TYPE(const float &) const -> short
458  {
459  return SQL_C_FLOAT;
460  }
461  template<> auto C_TYPE(const double &) const -> short
462  {
463  return SQL_C_DOUBLE;
464  }
465 
466  template<> auto C_TYPE(const unsigned char &) const -> short
467  {
468  return SQL_C_BINARY;
469  }
470  template<> auto C_TYPE(const unsigned short &) const -> short
471  {
472  return SQL_C_USHORT;
473  }
474  template<> auto C_TYPE(const unsigned long &) const -> short
475  {
476  return SQL_C_ULONG;
477  }
478  template<> auto C_TYPE(const unsigned long long &) const -> short
479  {
480  return SQL_C_UBIGINT;
481  }
482  template<> auto C_TYPE(const unsigned int &) const -> short
483  {
484  return SQL_C_UBIGINT;
485  }
486  template<> auto C_TYPE(const long double &) const -> short
487  {
488  return SQL_C_DOUBLE;
489  }
490 
491  template<> auto C_TYPE(const std::string &) const -> short
492  {
493  return SQL_C_CHAR;
494  }
495  template<> auto C_TYPE(const std::wstring &) const -> short
496  {
497  return SQL_C_WCHAR;
498  }
499  template<> auto C_TYPE(const ByteArray &) const -> short
500  {
501  return SQL_C_BINARY;
502  }
503 
504  template <typename T> auto SQL_TYPE(const T &) const -> short;
505  template<> auto SQL_TYPE(const bool &) const -> short
506  {
507  return SQL_BIT;
508  }
509  template<> auto SQL_TYPE(const char &) const -> short
510  {
511  return SQL_CHAR;
512  }
513  template<> auto SQL_TYPE(const short &) const -> short
514  {
515  return SQL_TINYINT;
516  }
517  template<> auto SQL_TYPE(const long &) const -> short
518  {
519  return SQL_INTEGER;
520  }
521  template<> auto SQL_TYPE(const long long &) const -> short
522  {
523  return SQL_BIGINT;
524  }
525  template<> auto SQL_TYPE(const int &) const -> short
526  {
527  return SQL_INTEGER;
528  }
529  template<> auto SQL_TYPE(const float &) const -> short
530  {
531  return SQL_FLOAT;
532  }
533  template<> auto SQL_TYPE(const double &) const -> short
534  {
535  return SQL_DOUBLE;
536  }
537 
538  template<> auto SQL_TYPE(const unsigned char &) const -> short
539  {
540  return SQL_BINARY;
541  }
542  template<> auto SQL_TYPE(const unsigned short &) const -> short
543  {
544  return SQL_TINYINT;
545  }
546  template<> auto SQL_TYPE(const unsigned long &) const -> short
547  {
548  return SQL_INTEGER;
549  }
550  template<> auto SQL_TYPE(const unsigned long long &) const -> short
551  {
552  return SQL_BIGINT;
553  }
554  template<> auto SQL_TYPE(const unsigned int &) const -> short
555  {
556  return SQL_INTEGER;
557  }
558  template<> auto SQL_TYPE(const long double &) const -> short
559  {
560  return SQL_DOUBLE;
561  }
562 
563  template<> auto SQL_TYPE(const std::string &) const -> short
564  {
565  return SQL_CHAR;
566  }
567  template<> auto SQL_TYPE(const std::wstring &) const -> short
568  {
569  return SQL_WCHAR;
570  }
571  template<> auto SQL_TYPE(const ByteArray &) const -> short
572  {
573  return SQL_BINARY;
574  }
575  };
576 };
577 };
void execute()
Execute the prepared sql statement.
void * hstmt
Handler of sql statement (OBDC)
size_t bindParameterCount
Count of binded parameters .
auto at(size_t index) const -> T
Get column&#39;s data by its index.
auto next() const -> bool
Move cursor to the next sql-statement.
auto size() const -> size_t
Get size of columns.
void free()
Free the sql statement.
SQLi * sqli
SQLi who created the SQLStatement.
void bindParameter(const T &val, const _Args &...args)
Get a column data by its name.
void refresh()
Refresh the sql statement.
auto get(const Key &key) -> T &
Get element.
Definition: HashMap.hpp:144
auto fetch() const -> bool
Fetch a record.
HashMap< size_t, SQL_SIZE_T > bindParameterBASizeMap
A map for binary size.
SQLStatement(SQLi *sqli)
Protected Constructor.
A SQL interface; DBMS connector.
Definition: SQLi.hpp:42
Binary data class.
Definition: ByteArray.hpp:29
void executeDirectly(const std::string &sql)
Execute sql-statement direclty.
void set(const Key &key, const T &val)
Set element.
Definition: HashMap.hpp:165
void prepare(const std::string &sql, const T &val, const _Args &...args)
Prepare a sql statement.