mysqlwrap.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <limits.h>
  5. #include <utility>
  6. #include <math.h>
  7. #include "mysqlwrap.h"
  8. CMySqlDB::CMySqlDB(void) : m_fIsInit(false)
  9. {
  10. memset(&m_mySql, 0, sizeof(m_mySql));
  11. Init();
  12. }
  13. CMySqlDB::~CMySqlDB(void)
  14. {
  15. Close();
  16. }
  17. bool CMySqlDB::Init(void) throw()
  18. {
  19. if(!m_fIsInit)
  20. m_fIsInit = !!mysql_init(&m_mySql);
  21. return m_fIsInit;
  22. }
  23. void CMySqlDB::Close(void) throw()
  24. {
  25. if(m_fIsInit)
  26. {
  27. mysql_close(&m_mySql);
  28. m_fIsInit = false;
  29. memset(&m_mySql, 0, sizeof(m_mySql));
  30. }
  31. }
  32. bool CMySqlDB::Connect( const char *host,
  33. const char *user,
  34. const char *pass,
  35. const char *db,
  36. unsigned int port,
  37. const char *unix_socket,
  38. unsigned long client_flag)
  39. {
  40. if(!Init())
  41. return false;
  42. return !!mysql_real_connect(&m_mySql, host, user, pass, db, port, unix_socket, client_flag);
  43. }
  44. int CMySqlDB::SetCharSet(const char *pszCharset)
  45. {
  46. return !mysql_set_character_set(&m_mySql, pszCharset);
  47. }
  48. int CMySqlDB::Options(enum mysql_option option, const void *arg)
  49. {
  50. return !mysql_options(&m_mySql, option, arg);
  51. }
  52. CMySqlResult CMySqlDB::Query(const char *sql)
  53. {
  54. bool bErr = true;
  55. MYSQL_RES *pRes = NULL;
  56. if(m_fIsInit)
  57. {
  58. if(!(bErr = !!mysql_query(&m_mySql, sql)))
  59. pRes = mysql_store_result(&m_mySql);
  60. }
  61. return CMySqlResult(pRes, bErr);
  62. }
  63. int CMySqlDB::SelectDB(const char *db)
  64. {
  65. return mysql_select_db(&m_mySql, db);
  66. }
  67. std::string CMySqlDB::EscapeStringQuote(const char *from, char quote)
  68. {
  69. if( m_fIsInit &&
  70. from && *from)
  71. {
  72. size_t len = strlen(from);
  73. size_t lenBuf = len * 2 + 1;
  74. char *buf = (char*)alloca(lenBuf);
  75. #if MYSQL_VERSION_ID >= 50706
  76. if(mysql_real_escape_string_quote(&m_mySql, buf, from, (unsigned long)len, quote))
  77. #else // MYSQL_VERSION_ID
  78. (void)quote;
  79. if(mysql_real_escape_string(&m_mySql, buf, from, (unsigned long)len))
  80. #endif // MYSQL_VERSION_ID
  81. return buf;
  82. }
  83. return "";
  84. }
  85. std::string CMySqlDB::EscapeString(const char *from)
  86. {
  87. if( m_fIsInit &&
  88. from && *from)
  89. {
  90. size_t len = strlen(from);
  91. size_t lenBuf = len * 2 + 1;
  92. char *buf = (char*)alloca(lenBuf);
  93. if(mysql_real_escape_string(&m_mySql, buf, from, (unsigned long)len))
  94. return buf;
  95. }
  96. return "";
  97. }
  98. std::string CMySqlDB::LastError(void)
  99. {
  100. if(m_fIsInit)
  101. return mysql_error(&m_mySql);
  102. else
  103. return "MySQL not initialized!";
  104. }
  105. unsigned int CMySqlDB::LastErrno(void)
  106. {
  107. if(m_fIsInit)
  108. return mysql_errno(&m_mySql);
  109. else
  110. return -1;
  111. }
  112. /////////////////////////////////////////////////////////////////////////////
  113. CMySqlResult::CMySqlResult(MYSQL_RES *pRes, bool err) : m_pRes(pRes),
  114. m_bError(err)
  115. {
  116. }
  117. CMySqlResult::~CMySqlResult(void)
  118. {
  119. Free();
  120. }
  121. void CMySqlResult::Free(void)
  122. {
  123. if(m_pRes)
  124. {
  125. mysql_free_result(m_pRes);
  126. m_pRes = NULL;
  127. }
  128. }
  129. my_ulonglong CMySqlResult::RowCount(void) const
  130. {
  131. if(m_pRes)
  132. return mysql_num_rows(m_pRes);
  133. return 0;
  134. }
  135. unsigned int CMySqlResult::FieldCount(void) const
  136. {
  137. if(m_pRes)
  138. return mysql_num_fields(m_pRes);
  139. return 0;
  140. }
  141. MYSQL_ROW CMySqlResult::FetchRow(void)
  142. {
  143. if(m_pRes)
  144. return mysql_fetch_row(m_pRes);
  145. return NULL;
  146. }
  147. bool CMySqlResult::FetchRow(CMySqlRow &row) const
  148. {
  149. if(m_pRes)
  150. {
  151. MYSQL_ROW pRow = mysql_fetch_row(m_pRes);
  152. if(pRow)
  153. return row.Create(FieldCount(), FetchFields(), pRow);
  154. }
  155. return false;
  156. }
  157. const MYSQL_FIELD * CMySqlResult::FetchFields(void) const
  158. {
  159. if(m_pRes)
  160. return mysql_fetch_fields(m_pRes);
  161. return NULL;
  162. }
  163. /////////////////////////////////////////////////////////////////////////////
  164. /////////////////////////////////////////////////////////////////////////////
  165. /////////////////////////////////////////////////////////////////////////////
  166. const CMySqlVar CMySqlRow::m_vNul;
  167. CMySqlRow::CMySqlRow(void) : m_bValid(false), m_nFieldCount(0)
  168. {
  169. }
  170. CMySqlRow::~CMySqlRow(void)
  171. {
  172. }
  173. void CMySqlRow::Clear(void)
  174. {
  175. m_bValid = false;
  176. m_nFieldCount = 0;
  177. m_fields.clear();
  178. }
  179. bool CMySqlRow::Create(unsigned int nFieldCount, const MYSQL_FIELD *pFields, MYSQL_ROW pRow)
  180. {
  181. Clear();
  182. if((nFieldCount > 0) && pFields && pRow)
  183. {
  184. for(m_nFieldCount = 0; m_nFieldCount < nFieldCount; ++m_nFieldCount)
  185. {
  186. std::string s(pFields[m_nFieldCount].name);
  187. if(!m_fields.emplace(s, std::move(CMySqlVar(pFields[m_nFieldCount], pRow[m_nFieldCount]))).second)
  188. {
  189. Clear();
  190. return false;
  191. }
  192. }
  193. m_bValid = true;
  194. }
  195. return m_bValid;
  196. }
  197. const CMySqlVar& CMySqlRow::Value(const char *pszFieldname) const
  198. {
  199. if(m_bValid)
  200. {
  201. CMySqlFieldMap::const_iterator it;
  202. if(FindField(pszFieldname, it))
  203. return it->second;
  204. }
  205. return m_vNul;
  206. }
  207. CMySqlRow::CMySqlFieldMap::const_iterator CMySqlRow::begin(void)
  208. {
  209. return m_fields.begin();
  210. }
  211. CMySqlRow::CMySqlFieldMap::const_iterator CMySqlRow::end(void)
  212. {
  213. return m_fields.end();
  214. }
  215. bool CMySqlRow::FindField(const char *pszFieldname, CMySqlFieldMap::const_iterator &it) const
  216. {
  217. if(m_bValid)
  218. {
  219. it = m_fields.find(pszFieldname);
  220. return (it != m_fields.end());
  221. }
  222. return false;
  223. }
  224. /////////////////////////////////////////////////////////////////////////////
  225. /////////////////////////////////////////////////////////////////////////////
  226. /////////////////////////////////////////////////////////////////////////////
  227. CMySqlVar::CMySqlVar(void)
  228. {
  229. Clear();
  230. }
  231. CMySqlVar::CMySqlVar(const MYSQL_FIELD &rField, const char *pszVal)
  232. {
  233. FromField(rField, pszVal);
  234. }
  235. CMySqlVar::CMySqlVar(CMySqlVar &&o) : m_bValid(std::move(o.m_bValid)), m_bInteger(std::move(o.m_bInteger)), m_bReal(std::move(o.m_bReal)), m_bUnsigned(std::move(o.m_bUnsigned)), m_bString(std::move(o.m_bString)),
  236. m_strVal(std::move(o.m_strVal)), m_strFieldname(std::move(o.m_strFieldname)), m_sqlFt(std::move(o.m_sqlFt)), m_numVal(std::move(o.m_numVal))
  237. {
  238. if(this != &o)
  239. o.Clear();
  240. }
  241. CMySqlVar::~CMySqlVar(void)
  242. {
  243. }
  244. void CMySqlVar::Clear(void)
  245. {
  246. m_bValid = false;
  247. m_bUnsigned = false;
  248. m_bInteger = false;
  249. m_bReal = false;
  250. m_bString = false;
  251. m_strFieldname.clear();
  252. m_strVal.clear();
  253. m_sqlFt = MYSQL_TYPE_NULL;
  254. m_numVal.uVal = 0;
  255. }
  256. bool CMySqlVar::FromField(const MYSQL_FIELD &rField, const char *pszVal)
  257. {
  258. Clear();
  259. if(pszVal)
  260. {
  261. char *pszEndPtr;
  262. bool bUnsigned = !!(rField.flags & UNSIGNED_FLAG);
  263. m_strFieldname = rField.name;
  264. switch(rField.type)
  265. {
  266. case MYSQL_TYPE_BIT:
  267. case MYSQL_TYPE_TINY: // 8 Bit => 8 Bit
  268. case MYSQL_TYPE_SHORT: // 16 Bit => 16 Bit
  269. case MYSQL_TYPE_INT24: // 24 Bit => 32 Bit
  270. case MYSQL_TYPE_LONG: // 32 Bit => 32 Bit
  271. case MYSQL_TYPE_LONGLONG: // 64 Bit => 64 Bit
  272. if(bUnsigned)
  273. {
  274. int64_t val = strtoll(pszVal, &pszEndPtr, 10);
  275. if(!*pszVal || ((val == LLONG_MIN || val == LLONG_MAX) && errno == ERANGE) || *pszEndPtr)
  276. m_bValid = false;
  277. else
  278. {
  279. m_sqlFt = rField.type;
  280. m_strVal = pszVal;
  281. m_numVal.iVal = val;
  282. m_bUnsigned = true;
  283. m_bInteger = true;
  284. m_bValid = true;
  285. }
  286. }
  287. else
  288. {
  289. uint64_t val = strtoull(pszVal, &pszEndPtr, 10);
  290. if(!*pszVal || (val == ULLONG_MAX && errno == ERANGE) || *pszEndPtr)
  291. m_bValid = false;
  292. else
  293. {
  294. m_sqlFt = rField.type;
  295. m_strVal = pszVal;
  296. m_numVal.uVal = val;
  297. m_bInteger = true;
  298. m_bValid = true;
  299. }
  300. }
  301. break;
  302. case MYSQL_TYPE_FLOAT:
  303. case MYSQL_TYPE_DOUBLE:
  304. case MYSQL_TYPE_DECIMAL:
  305. case MYSQL_TYPE_NEWDECIMAL:
  306. {
  307. double val = strtod(pszVal, &pszEndPtr);
  308. if(!*pszVal || ((val == HUGE_VAL || val == -HUGE_VAL) && errno == ERANGE) || *pszEndPtr)
  309. m_bValid = false;
  310. else
  311. {
  312. m_sqlFt = rField.type;
  313. m_strVal = pszVal;
  314. m_numVal.fVal = val;
  315. m_bReal = true;
  316. m_bValid = true;
  317. }
  318. }
  319. break;
  320. case MYSQL_TYPE_VARCHAR:
  321. case MYSQL_TYPE_VAR_STRING:
  322. case MYSQL_TYPE_STRING:
  323. m_sqlFt = rField.type;
  324. m_strVal = pszVal;
  325. m_bString = true;
  326. m_bValid = true;
  327. break;
  328. case MYSQL_TYPE_DATE:
  329. case MYSQL_TYPE_TIME:
  330. case MYSQL_TYPE_TIMESTAMP:
  331. case MYSQL_TYPE_DATETIME:
  332. case MYSQL_TYPE_YEAR:
  333. case MYSQL_TYPE_NEWDATE:
  334. case MYSQL_TYPE_ENUM:
  335. case MYSQL_TYPE_SET:
  336. case MYSQL_TYPE_TINY_BLOB:
  337. case MYSQL_TYPE_MEDIUM_BLOB:
  338. case MYSQL_TYPE_LONG_BLOB:
  339. case MYSQL_TYPE_BLOB:
  340. case MYSQL_TYPE_GEOMETRY:
  341. break;
  342. case MYSQL_TYPE_NULL:
  343. m_sqlFt = rField.type;
  344. m_strVal = "";
  345. m_bValid = true;
  346. break;
  347. default:
  348. break;
  349. }
  350. }
  351. return m_bValid;
  352. }