DBResult_ptr DatabaseODBC::internalSelectQuery(const std::string &query) { if(!m_connected) return DBResult_ptr(); #ifdef __DEBUG_SQL__ std::cout << "ODBC QUERY: " << query << std::endl; #endif std::string buf = _parse(query); SQLHSTMT stmt; SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, m_handle, &stmt); if(!RETURN_SUCCESS(ret)){ std::cout << "Failed to allocate ODBC SQLHSTMT statement." << std::endl; return DBResult_ptr(); } ret = SQLExecDirect(stmt, (SQLCHAR*)buf.c_str(), buf.length() ); if(!RETURN_SUCCESS(ret)){ std::cout << "SQLExecDirect(): " << query << ": ODBC ERROR." << std::endl; return DBResult_ptr(); } DBResult_ptr results(new ODBCResult(stmt), boost::bind(&DatabaseDriver::freeResult, this, _1)); return verifyResult(results); }
DBResult_ptr Database::storeQuery(const std::string& query) { // executes the query database_lock.lock(); retry: while (mysql_real_query(m_handle, query.c_str(), query.length()) != 0) { std::cout << "[Error - mysql_real_query] Query: " << query << std::endl << "Message: " << mysql_error(m_handle) << std::endl; auto error = mysql_errno(m_handle); if (error != CR_SERVER_LOST && error != CR_SERVER_GONE_ERROR && error != CR_CONN_HOST_ERROR && error != 1053/*ER_SERVER_SHUTDOWN*/ && error != CR_CONNECTION_ERROR) { break; } std::this_thread::sleep_for(std::chrono::seconds(1)); } // we should call that every time as someone would call executeQuery('SELECT...') // as it is described in MySQL manual: "it doesn't hurt" :P MYSQL_RES* m_res = mysql_store_result(m_handle); // error occured if (!m_res) { std::cout << "[Error - mysql_store_result] Query: " << query << std::endl << "Message: " << mysql_error(m_handle) << std::endl; int error = mysql_errno(m_handle); if (error != CR_SERVER_LOST && error != CR_SERVER_GONE_ERROR && error != CR_CONN_HOST_ERROR && error != 1053/*ER_SERVER_SHUTDOWN*/ && error != CR_CONNECTION_ERROR) { database_lock.unlock(); return nullptr; } goto retry; } database_lock.unlock(); // retriving results of query return verifyResult(DBResult_ptr(new DBResult(m_res))); }
DBResult_ptr DatabaseDriver::verifyResult(DBResult_ptr result) { if(!result->advance()){ return DBResult_ptr(); } else{ return result; } }
DBResult_ptr DatabaseMySQL::internalSelectQuery(const std::string &query) { if(!m_connected) return DBResult_ptr(); #ifdef __DEBUG_SQL__ std::cout << "MYSQL QUERY: " << query << std::endl; #endif // executes the query if(mysql_real_query(&m_handle, query.c_str(), query.length()) != 0){ std::cout << "mysql_real_query(): " << query << ": MYSQL ERROR: " << mysql_error(&m_handle) << std::endl; int error = mysql_errno(&m_handle); if(error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR){ m_connected = false; } } // we should call that every time as someone would call executeQuery('SELECT...') // as it is described in MySQL manual: "it doesn't hurt" :P MYSQL_RES* m_res = mysql_store_result(&m_handle); // error occured if(!m_res){ std::cout << "mysql_store_result(): " << query.substr(0, 256) << ": MYSQL ERROR: " << mysql_error(&m_handle) << std::endl; int error = mysql_errno(&m_handle); if(error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR){ m_connected = false; } return DBResult_ptr(); } // retriving results of query DBResult_ptr res(new MySQLResult(m_res), boost::bind(&DatabaseDriver::freeResult, this, _1)); return verifyResult(res); }
DBResult_ptr DatabaseSQLite::internalSelectQuery(const std::string &query) { boost::recursive_mutex::scoped_lock lockClass(sqliteLock); if(!m_connected) return DBResult_ptr(); #ifdef __DEBUG_SQL__ std::cout << "SQLITE QUERY: " << query << std::endl; #endif std::string buf = _parse(query); sqlite3_stmt* stmt; // prepares statement if( OTS_SQLITE3_PREPARE(m_handle, buf.c_str(), buf.length(), &stmt, NULL) != SQLITE_OK){ sqlite3_finalize(stmt); std::cout << "OTS_SQLITE3_PREPARE(): SQLITE ERROR: " << sqlite3_errmsg(m_handle) << " (" << buf << ")" << std::endl; return DBResult_ptr(); } DBResult_ptr results(new SQLiteResult(stmt), boost::bind(&DatabaseDriver::freeResult, this, _1)); return verifyResult(results); }
DBResult_ptr SQLiteResult::advance() { // checks if after moving to next step we have a row result bool m_rowAvailable = (sqlite3_step(m_handle) == SQLITE_ROW); return m_rowAvailable ? shared_from_this() : DBResult_ptr(); }
DBResult_ptr MySQLResult::advance() { m_row = mysql_fetch_row(m_handle); return m_row != NULL ? shared_from_this() : DBResult_ptr(); }
DBResult_ptr ODBCResult::advance() { SQLRETURN ret = SQLFetch(m_handle); m_rowAvailable = RETURN_SUCCESS(ret); return m_rowAvailable ? shared_from_this() : DBResult_ptr(); }