Advertisement
Guest User

Untitled

a guest
Mar 1st, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.75 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. ////////////////////////////////////////////////////////////////////////
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ////////////////////////////////////////////////////////////////////////
  17. // C++ Implementation: databaseodbc
  18. // Description: Frontend for ODBC connections
  19. //
  20. // Author: Bruno R Ferreira <brf_coldf@yahoo.com.br>, (C) 2007
  21. ////////////////////////////////////////////////////////////////////////
  22. #include "otpch.h"
  23. #include <iostream>
  24.  
  25. #include "database.h"
  26. #include "databaseodbc.h"
  27.  
  28. #include "configmanager.h"
  29. extern ConfigManager g_config;
  30.  
  31. #define RETURN_SUCCESS(ret) (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
  32.  
  33. DatabaseODBC::DatabaseODBC()
  34. {
  35. m_connected = false;
  36.  
  37. char* dns = new char[SQL_MAX_DSN_LENGTH];
  38. char* user = new char[32];
  39. char* pass = new char[32];
  40.  
  41. strcpy((char*)dns, g_config.getString(ConfigManager::SQL_DB).c_str());
  42. strcpy((char*)user, g_config.getString(ConfigManager::SQL_USER).c_str());
  43. strcpy((char*)pass, g_config.getString(ConfigManager::SQL_PASS).c_str());
  44.  
  45. SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_env);
  46. if(!RETURN_SUCCESS(ret))
  47. {
  48. std::cout << "Failed to allocate ODBC SQLHENV enviroment handle." << std::endl;
  49. m_env = NULL;
  50. return;
  51. }
  52.  
  53. ret = SQLSetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
  54. if(!RETURN_SUCCESS(ret))
  55. {
  56. std::cout << "SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION): Failed to switch to ODBC 3 version." << std::endl;
  57. SQLFreeHandle(SQL_HANDLE_ENV, m_env);
  58. m_env = NULL;
  59. }
  60.  
  61. if(m_env == NULL)
  62. {
  63. std::cout << "ODBC SQLHENV enviroment not initialized." << std::endl;
  64. return;
  65. }
  66.  
  67. ret = SQLAllocHandle(SQL_HANDLE_DBC, m_env, &m_handle);
  68. if(!RETURN_SUCCESS(ret))
  69. {
  70. std::cout << "Failed to allocate ODBC SQLHDBC connection handle." << std::endl;
  71. m_handle = NULL;
  72. return;
  73. }
  74.  
  75. ret = SQLSetConnectAttr(m_handle, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER*)5, 0);
  76. if(!RETURN_SUCCESS(ret))
  77. {
  78. std::cout << "SQLSetConnectAttr(SQL_ATTR_CONNECTION_TIMEOUT): Failed to set connection timeout." << std::endl;
  79. SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
  80. m_handle = NULL;
  81. return;
  82. }
  83.  
  84. ret = SQLConnect(m_handle, (SQLCHAR*)dns, SQL_NTS, (SQLCHAR*)user, SQL_NTS, (SQLCHAR*)pass, SQL_NTS);
  85. if(!RETURN_SUCCESS(ret))
  86. {
  87. std::cout << "Failed to connect to ODBC via DSN: " << dns << " (user " << user << ")" << std::endl;
  88. SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
  89. m_handle = NULL;
  90. return;
  91. }
  92.  
  93. m_connected = true;
  94. }
  95.  
  96. DatabaseODBC::~DatabaseODBC()
  97. {
  98. if(m_connected)
  99. {
  100. SQLDisconnect(m_handle);
  101. SQLFreeHandle(SQL_HANDLE_DBC, m_handle);
  102. m_handle = NULL;
  103. m_connected = false;
  104. }
  105.  
  106. SQLFreeHandle(SQL_HANDLE_ENV, m_env);
  107. }
  108.  
  109. bool DatabaseODBC::getParam(DBParam_t param)
  110. {
  111. switch(param)
  112. {
  113. case DBPARAM_MULTIINSERT:
  114. default:
  115. break;
  116. }
  117.  
  118. return false;
  119. }
  120.  
  121. bool DatabaseODBC::beginTransaction()
  122. {
  123. return true;
  124. // return executeQuery("BEGIN");
  125. }
  126.  
  127. bool DatabaseODBC::rollback()
  128. {
  129. return true;
  130. // SQL_RETURN ret = SQLTransact(m_env, m_handle, SQL_ROLLBACK);
  131. // return RETURN_SUCCESS(ret);
  132. }
  133.  
  134. bool DatabaseODBC::commit()
  135. {
  136. return true;
  137. // SQL_RETURN ret = SQLTransact(m_env, m_handle, SQL_COMMIT);
  138. // return RETURN_SUCCESS(ret);
  139. }
  140.  
  141. bool DatabaseODBC::executeQuery(const std::string& query)
  142. {
  143. if(!m_connected)
  144. return false;
  145.  
  146. #ifdef __SQL_QUERY_DEBUG__
  147. std::cout << "ODBC QUERY: " << query << std::endl;
  148. #endif
  149.  
  150. SQLHSTMT stmt;
  151. SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, m_handle, &stmt);
  152. if(!RETURN_SUCCESS(ret))
  153. {
  154. std::cout << "Failed to allocate ODBC SQLHSTMT statement." << std::endl;
  155. return false;
  156. }
  157.  
  158. std::string buf = _parse(query);
  159. ret = SQLExecDirect(stmt, (SQLCHAR*)buf.c_str(), buf.length());
  160. if(!RETURN_SUCCESS(ret))
  161. {
  162. std::cout << "SQLExecDirect(): " << query << ": ODBC ERROR." << std::endl;
  163. return false;
  164. }
  165.  
  166. return true;
  167. }
  168.  
  169. DBResult* DatabaseODBC::storeQuery(const std::string& query)
  170. {
  171. if(!m_connected)
  172. return NULL;
  173.  
  174. #ifdef __SQL_QUERY_DEBUG__
  175. std::cout << "ODBC QUERY: " << query << std::endl;
  176. #endif
  177.  
  178. SQLHSTMT stmt;
  179. SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, m_handle, &stmt);
  180. if(!RETURN_SUCCESS(ret))
  181. {
  182. std::cout << "Failed to allocate ODBC SQLHSTMT statement." << std::endl;
  183. return NULL;
  184. }
  185.  
  186. std::string buf = _parse(query);
  187. ret = SQLExecDirect(stmt, (SQLCHAR*)buf.c_str(), buf.length() );
  188. if(!RETURN_SUCCESS(ret))
  189. {
  190. std::cout << "SQLExecDirect(): " << query << ": ODBC ERROR." << std::endl;
  191. return NULL;
  192. }
  193.  
  194. DBResult* results = (DBResult*)new ODBCResult(stmt);
  195. return verifyResult(results);
  196. }
  197.  
  198. std::string DatabaseODBC::escapeBlob(const char *s, uint32_t length)
  199. {
  200. std::string buf = "'";
  201. for(uint32_t i = 0; i < length; i++)
  202. {
  203. switch(s[i])
  204. {
  205. case '\'':
  206. buf += "\'\'";
  207. break;
  208.  
  209. case '\0':
  210. buf += "\\0";
  211. break;
  212.  
  213. case '\\':
  214. buf += "\\\\";
  215. break;
  216.  
  217. case '\r':
  218. buf += "\\r";
  219. break;
  220.  
  221. case '\n':
  222. buf += "\\n";
  223. break;
  224.  
  225. default:
  226. buf += s[i];
  227. }
  228. }
  229.  
  230. buf += "'";
  231. return buf;
  232. }
  233.  
  234. std::string DatabaseODBC::_parse(const std::string& s)
  235. {
  236. std::string query = "";
  237. query.reserve(s.size());
  238.  
  239. bool inString = false;
  240. for(uint32_t a = 0; a < s.length(); a++)
  241. {
  242. uint8_t ch = s[a];
  243. if(ch == '\'')
  244. {
  245. if(inString && s[a + 1] != '\'')
  246. inString = false;
  247. else
  248. inString = true;
  249. }
  250.  
  251. if(ch == '`' && !inString)
  252. ch = '"';
  253.  
  254. query += ch;
  255. }
  256.  
  257. return query;
  258. }
  259.  
  260. int32_t ODBCResult::getDataInt(const std::string& s)
  261. {
  262. listNames_t::iterator it = m_listNames.find(s);
  263. if(it != m_listNames.end())
  264. {
  265. int32_t value;
  266. SQLRETURN ret = SQLGetData(m_handle, it->second, SQL_C_SLONG, &value, 0, NULL);
  267.  
  268. if(RETURN_SUCCESS(ret))
  269. return value;
  270. else
  271. std::cout << "Error during getDataInt(" << s << ")." << std::endl;
  272. }
  273.  
  274. std::cout << "Error during getDataInt(" << s << ")." << std::endl;
  275. return 0; // Failed
  276. }
  277.  
  278. int64_t ODBCResult::getDataLong(const std::string& s)
  279. {
  280. listNames_t::iterator it = m_listNames.find(s);
  281. if(it != m_listNames.end())
  282. {
  283. int64_t value;
  284. SQLRETURN ret = SQLGetData(m_handle, it->second, SQL_C_SBIGINT, &value, 0, NULL);
  285.  
  286. if(RETURN_SUCCESS(ret))
  287. return value;
  288. else
  289. std::cout << "Error during getDataLong(" << s << ")." << std::endl;
  290. }
  291.  
  292. std::cout << "Error during getDataLong(" << s << ")." << std::endl;
  293. return 0; // Failed
  294. }
  295.  
  296. std::string ODBCResult::getDataString(const std::string& s)
  297. {
  298. listNames_t::iterator it = m_listNames.find(s);
  299. if(it != m_listNames.end())
  300. {
  301. char* value = new char[1024];
  302. SQLRETURN ret = SQLGetData(m_handle, it->second, SQL_C_CHAR, value, 1024, NULL);
  303.  
  304. if(RETURN_SUCCESS(ret))
  305. {
  306. std::string buff = std::string(value);
  307. return buff;
  308. }
  309. else
  310. std::cout << "Error during getDataString(" << s << ")." << std::endl;
  311. }
  312.  
  313. std::cout << "Error during getDataString(" << s << ")." << std::endl;
  314. return std::string(""); // Failed
  315. }
  316.  
  317. const char* ODBCResult::getDataStream(const std::string& s, uint64_t& size)
  318. {
  319. listNames_t::iterator it = m_listNames.find(s);
  320. if(it != m_listNames.end())
  321. {
  322. char* value = new char[1024];
  323. if(RETURN_SUCCESS(SQLGetData(m_handle, it->second, SQL_C_BINARY, value, 1024, (SQLLEN*)&size)))
  324. return value;
  325. }
  326.  
  327. std::cout << "Error during getDataStream(" << s << ")." << std::endl;
  328. size = 0;
  329. return 0; // Failed
  330. }
  331.  
  332. void ODBCResult::free()
  333. {
  334. if(m_handle)
  335. {
  336. SQLFreeHandle(SQL_HANDLE_STMT, m_handle);
  337. delete this;
  338. }
  339. else
  340. std::cout << "[Warning - ODBCResult::free] Trying to free already freed result." << std::endl;
  341. }
  342.  
  343. bool ODBCResult::next()
  344. {
  345. SQLRETURN ret = SQLFetch(m_handle);
  346. return RETURN_SUCCESS(ret);
  347. }
  348.  
  349. ODBCResult::ODBCResult(SQLHSTMT stmt)
  350. {
  351. if(!stmt)
  352. {
  353. delete this;
  354. return;
  355. }
  356.  
  357. m_handle = stmt;
  358. int16_t numCols = 0;
  359.  
  360. SQLNumResultCols(m_handle, &numCols);
  361. for(int32_t i = 1; i <= numCols; i++)
  362. {
  363. char* name = new char[129];
  364. SQLDescribeCol(m_handle, i, (SQLCHAR*)name, 129, NULL, NULL, NULL, NULL, NULL);
  365. m_listNames[name] = i;
  366. }
  367. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement