root/trunk/src/shared/Database/SqlOperations.cpp @ 19

Revision 2, 5.5 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
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 2 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, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19#include "SqlOperations.h"
20#include "SqlDelayThread.h"
21#include "DatabaseEnv.h"
22#include "DatabaseImpl.h"
23
24/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
25
26void SqlStatement::Execute(Database *db)
27{
28    /// just do it
29    db->DirectExecute(m_sql);
30}
31
32void SqlTransaction::Execute(Database *db)
33{
34    if(m_queue.empty())
35        return;
36    db->DirectExecute("START TRANSACTION");
37    while(!m_queue.empty())
38    {
39        char const *sql = m_queue.front();
40        m_queue.pop();
41
42        if(!db->DirectExecute(sql))
43        {
44            free((void*)const_cast<char*>(sql));
45            db->DirectExecute("ROLLBACK");
46            while(!m_queue.empty())
47            {
48                free((void*)const_cast<char*>(m_queue.front()));
49                m_queue.pop();
50            }
51            return;
52        }
53
54        free((void*)const_cast<char*>(sql));
55    }
56    db->DirectExecute("COMMIT");
57}
58
59/// ---- ASYNC QUERIES ----
60
61void SqlQuery::Execute(Database *db)
62{
63    if(!m_callback || !m_queue)
64        return;
65    /// execute the query and store the result in the callback
66    m_callback->SetResult(db->Query(m_sql));
67    /// add the callback to the sql result queue of the thread it originated from
68    m_queue->add(m_callback);
69}
70
71void SqlResultQueue::Update()
72{
73    /// execute the callbacks waiting in the synchronization queue
74    while(!empty())
75    {
76        MaNGOS::IQueryCallback * callback = next();
77        callback->Execute();
78        delete callback;
79    }
80}
81
82void SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue)
83{
84    if(!callback || !thread || !queue)
85        return;
86
87    /// delay the execution of the queries, sync them with the delay thread
88    /// which will in turn resync on execution (via the queue) and call back
89    SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue);
90    thread->Delay(holderEx);
91}
92
93bool SqlQueryHolder::SetQuery(size_t index, const char *sql)
94{
95    if(m_queries.size() <= index)
96    {
97        sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,m_queries.size(),sql);
98        return false;
99    }
100
101    if(m_queries[index].first != NULL)
102    {
103        sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",index,m_queries.size(),m_queries[index].first,sql);
104        return false;
105    }
106
107    /// not executed yet, just stored (it's not called a holder for nothing)
108    m_queries[index] = SqlResultPair(strdup(sql), NULL);
109    return true;
110}
111
112bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
113{
114    if(!format)
115    {
116        sLog.outError("Query (index: %u) is empty.",index);
117        return false;
118    }
119
120    va_list ap;
121    char szQuery [MAX_QUERY_LEN];
122    va_start(ap, format);
123    int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
124    va_end(ap);
125
126    if(res==-1)
127    {
128        sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
129        return false;
130    }
131
132    return SetQuery(index,szQuery);
133}
134
135QueryResult* SqlQueryHolder::GetResult(size_t index)
136{
137    if(index < m_queries.size())
138    {
139        /// the query strings are freed on the first GetResult or in the destructor
140        if(m_queries[index].first != NULL)
141        {
142            free((void*)(const_cast<char*>(m_queries[index].first)));
143            m_queries[index].first = NULL;
144        }
145        /// when you get a result aways remember to delete it!
146        return m_queries[index].second;
147    }
148    else
149        return NULL;
150}
151
152void SqlQueryHolder::SetResult(size_t index, QueryResult *result)
153{
154    /// store the result in the holder
155    if(index < m_queries.size())
156        m_queries[index].second = result;
157}
158
159SqlQueryHolder::~SqlQueryHolder()
160{
161    for(size_t i = 0; i < m_queries.size(); i++)
162    {
163        /// if the result was never used, free the resources
164        /// results used already (getresult called) are expected to be deleted
165        if(m_queries[i].first != NULL)
166        {
167            free((void*)(const_cast<char*>(m_queries[i].first)));
168            if(m_queries[i].second)
169                delete m_queries[i].second;
170        }
171    }
172}
173
174void SqlQueryHolder::SetSize(size_t size)
175{
176    /// to optimize push_back, reserve the number of queries about to be executed
177    m_queries.resize(size);
178}
179
180void SqlQueryHolderEx::Execute(Database *db)
181{
182    if(!m_holder || !m_callback || !m_queue)
183        return;
184
185    /// we can do this, we are friends
186    std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries;
187
188    for(size_t i = 0; i < queries.size(); i++)
189    {
190        /// execute all queries in the holder and pass the results
191        char const *sql = queries[i].first;
192        if(sql) m_holder->SetResult(i, db->Query(sql));
193    }
194
195    /// sync with the caller thread
196    m_queue->add(m_callback);
197}
Note: See TracBrowser for help on using the browser.