OregonCore  revision 3611e8a-git
Your Favourite TBC server
SqlOperations.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "SqlOperations.h"
19 #include "SqlDelayThread.h"
20 #include "DatabaseEnv.h"
21 #include "DatabaseImpl.h"
22 
23 // ASYNC STATEMENTS / TRANSACTIONS
24 
26 {
27  // just do it
28  db->DirectExecute(m_sql);
29 }
30 
31 // ASYNC QUERIES
32 
34 {
35  if (!m_callback || !m_queue)
36  return;
37 
38  // execute the query and store the result in the callback
39  m_callback->SetResult(db->Query(m_sql));
40  // add the callback to the sql result queue of the thread it originated from
41  m_queue->add(m_callback);
42 }
43 
45 {
46  // execute the callbacks waiting in the synchronization queue
47  Oregon::IQueryCallback* callback;
48  while (next(callback))
49  {
50  callback->Execute();
51  delete callback;
52  }
53 }
54 
56 {
57  if (!callback || !thread || !queue)
58  return false;
59 
60  // delay the execution of the queries, sync them with the delay thread
61  // which will in turn resync on execution (via the queue) and call back
62  SqlQueryHolderEx* holderEx = new SqlQueryHolderEx(this, callback, queue);
63  thread->Delay(holderEx);
64  return true;
65 }
66 
67 bool SqlQueryHolder::SetQuery(size_t index, const char* sql)
68 {
69  if (m_queries.size() <= index)
70  {
71  sLog.outError("Query index (%lu) out of range (size: %u) for query: %s", index, (uint32)m_queries.size(), sql);
72  return false;
73  }
74 
75  if (m_queries[index].first != NULL)
76  {
77  sLog.outError("Attempt assign query to holder index (%lu) where other query stored (Old: [%s] New: [%s])",
78  index, m_queries[index].first, sql);
79  return false;
80  }
81 
82  // not executed yet, just stored (it's not called a holder for nothing)
83  m_queries[index] = SqlResultPair(strdup(sql), QueryResult_AutoPtr(NULL));
84  return true;
85 }
86 
87 bool SqlQueryHolder::SetPQuery(size_t index, const char* format, ...)
88 {
89  if (!format)
90  {
91  sLog.outError("Query (index: %lu) is empty.", index);
92  return false;
93  }
94 
95  va_list ap;
96  char szQuery [MAX_QUERY_LEN];
97  va_start(ap, format);
98  int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
99  va_end(ap);
100 
101  if (res == -1)
102  {
103  sLog.outError("SQL Query truncated (and not execute) for format: %s", format);
104  return false;
105  }
106 
107  return SetQuery(index, szQuery);
108 }
109 
111 {
112  if (index < m_queries.size())
113  {
114  // the query strings are freed on the first GetResult or in the destructor
115  if (m_queries[index].first != NULL)
116  {
117  free((void*)(const_cast<char*>(m_queries[index].first)));
118  m_queries[index].first = NULL;
119  }
120  // when you get a result aways remember to delete it!
121  return m_queries[index].second;
122  }
123  else
124  return QueryResult_AutoPtr(NULL);
125 }
126 
128 {
129  // store the result in the holder
130  if (index < m_queries.size())
131  m_queries[index].second = result;
132 }
133 
135 {
136  for (size_t i = 0; i < m_queries.size(); i++)
137  {
138  // if the result was never used, free the resources
139  // results used already (getresult called) are expected to be deleted
140  if (m_queries[i].first != NULL)
141  free((void*)(const_cast<char*>(m_queries[i].first)));
142  }
143 }
144 
145 void SqlQueryHolder::SetSize(size_t size)
146 {
147  // to optimize push_back, reserve the number of queries about to be executed
148  m_queries.resize(size);
149 }
150 
152 {
153  if (!m_holder || !m_callback || !m_queue)
154  return;
155 
156  // we can do this, we are friends
157  std::vector<SqlQueryHolder::SqlResultPair>& queries = m_holder->m_queries;
158 
159  for (size_t i = 0; i < queries.size(); i++)
160  {
161  // execute all queries in the holder and pass the results
162  char const* sql = queries[i].first;
163  if (sql) m_holder->SetResult(i, db->Query(sql));
164  }
165 
166  // sync with the caller thread
167  m_queue->add(m_callback);
168 }
169 
bool Execute(Oregon::IQueryCallback *callback, SqlDelayThread *thread, SqlResultQueue *queue)
bool bool DirectExecute(const char *sql)
Definition: Database.h:115
#define sLog
Log class singleton.
Definition: Log.h:187
bool SetQuery(size_t index, const char *sql)
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
void SetResult(size_t index, QueryResult_AutoPtr result)
const char * m_sql
Definition: SqlOperations.h:53
void Execute(Database *db)
void Execute(Database *db)
bool void SetSize(size_t size)
bool Delay(SqlOperation *sql)
void Execute(Database *db)
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
QueryResult_AutoPtr GetResult(size_t index)
ACE_UINT32 uint32
Definition: Define.h:71
virtual void Execute()=0
#define vsnprintf
Definition: Common.h:131
bool SetPQuery(size_t index, const char *format,...) ATTR_PRINTF(3
std::pair< const char *, QueryResult_AutoPtr > SqlResultPair
#define MAX_QUERY_LEN
Definition: Database.h:44