-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
*
- * InspIRCd: (C) 2002-2010 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2006-2007, 2009 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2006-2009 Craig Edwards <craigedwards@brainbox.cc>
+ * Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
*
- * This program is free but copyrighted software; see
- * the file COPYING for details.
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
*
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
/* Stop mysql wanting to use long long */
#define NO_CLIENT_LONG_LONG
#include "inspircd.h"
#include <mysql.h>
-#include "sql.h"
+#include "modules/sql.h"
-#ifdef WINDOWS
-#pragma comment(lib, "mysqlclient.lib")
+#ifdef _WIN32
+# pragma comment(lib, "mysqlclient.lib")
+# pragma comment(lib, "advapi32.lib")
+# pragma comment(linker, "/NODEFAULTLIB:LIBCMT")
#endif
/* VERSION 3 API: With nonblocking (threaded) requests */
/* $ModDesc: SQL Service Provider module for all other m_sql* modules */
/* $CompileFlags: exec("mysql_config --include") */
/* $LinkerFlags: exec("mysql_config --libs_r") rpath("mysql_config --libs_r") */
-/* $ModDep: m_sqlv2.h */
/* THE NONBLOCKING MYSQL API!
*
struct QQueueItem
{
SQLQuery* q;
+ std::string query;
SQLConnection* c;
- QQueueItem(SQLQuery* Q, SQLConnection* C) : q(Q), c(C) {}
+ QQueueItem(SQLQuery* Q, const std::string& S, SQLConnection* C) : q(Q), query(S), c(C) {}
};
struct RQueueItem
}
- ~MySQLresult()
- {
- }
-
virtual int Rows()
{
return rows;
// This constructor creates an SQLConnection object with the given credentials, but does not connect yet.
SQLConnection(Module* p, ConfigTag* tag) : SQLProvider(p, "SQL/" + tag->getString("id")),
- config(tag)
+ config(tag), connection(NULL)
{
}
return true;
}
- virtual std::string FormatQuery(const std::string& q, const ParamL& p)
+ ModuleSQL* Parent()
+ {
+ return (ModuleSQL*)(Module*)creator;
+ }
+
+ MySQLresult* DoBlockingQuery(const std::string& query)
+ {
+
+ /* Parse the command string and dispatch it to mysql */
+ if (CheckConnection() && !mysql_real_query(connection, query.data(), query.length()))
+ {
+ /* Successfull query */
+ MYSQL_RES* res = mysql_use_result(connection);
+ unsigned long rows = mysql_affected_rows(connection);
+ return new MySQLresult(res, rows);
+ }
+ else
+ {
+ /* XXX: See /usr/include/mysql/mysqld_error.h for a list of
+ * possible error numbers and error messages */
+ SQLerror e(SQL_QREPLY_FAIL, ConvToStr(mysql_errno(connection)) + ": " + mysql_error(connection));
+ return new MySQLresult(e);
+ }
+ }
+
+ bool CheckConnection()
+ {
+ if (!connection || mysql_ping(connection) != 0)
+ return Connect();
+ return true;
+ }
+
+ std::string GetError()
+ {
+ return mysql_error(connection);
+ }
+
+ void Close()
+ {
+ mysql_close(connection);
+ }
+
+ void submit(SQLQuery* q, const std::string& qs)
+ {
+ Parent()->Dispatcher->LockQueue();
+ Parent()->qq.push_back(QQueueItem(q, qs, this));
+ Parent()->Dispatcher->UnlockQueueWakeup();
+ }
+
+ void submit(SQLQuery* call, const std::string& q, const ParamL& p)
{
std::string res;
unsigned int param = 0;
res.push_back(q[i]);
else
{
- // TODO numbered parameter support ('?1')
if (param < p.size())
{
std::string parm = p[param++];
}
}
}
- return res;
+ submit(call, res);
}
- std::string FormatQuery(const std::string& q, const ParamM& p)
+ void submit(SQLQuery* call, const std::string& q, const ParamM& p)
{
std::string res;
for(std::string::size_type i = 0; i < q.length(); i++)
{
std::string field;
i++;
- while (i < q.length() && isalpha(q[i]))
+ while (i < q.length() && isalnum(q[i]))
field.push_back(q[i++]);
i--;
}
}
}
- return res;
- }
-
- ModuleSQL* Parent()
- {
- return (ModuleSQL*)(Module*)creator;
- }
-
- MySQLresult* DoBlockingQuery(SQLQuery* req)
- {
-
- /* Parse the command string and dispatch it to mysql */
- if (CheckConnection() && !mysql_real_query(connection, req->query.data(), req->query.length()))
- {
- /* Successfull query */
- MYSQL_RES* res = mysql_use_result(connection);
- unsigned long rows = mysql_affected_rows(connection);
- return new MySQLresult(res, rows);
- }
- else
- {
- /* XXX: See /usr/include/mysql/mysqld_error.h for a list of
- * possible error numbers and error messages */
- SQLerror e(SQL_QREPLY_FAIL, ConvToStr(mysql_errno(connection)) + std::string(": ") + mysql_error(connection));
- return new MySQLresult(e);
- }
- }
-
- bool CheckConnection()
- {
- if (mysql_ping(connection) != 0)
- {
- return Connect();
- }
- else return true;
- }
-
- std::string GetError()
- {
- return mysql_error(connection);
- }
-
- void Close()
- {
- mysql_close(connection);
- }
-
- void submit(SQLQuery* q)
- {
- Parent()->Dispatcher->LockQueue();
- Parent()->qq.push_back(QQueueItem(q, this));
- Parent()->Dispatcher->UnlockQueueWakeup();
+ submit(call, res);
}
};
ServerInstance->Threads->Start(Dispatcher);
Implementation eventlist[] = { I_OnRehash, I_OnUnloadModule };
- ServerInstance->Modules->Attach(eventlist, this, 2);
+ ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+
+ OnRehash(NULL);
}
ModuleSQL::~ModuleSQL()
{
SQLerror err(SQL_BAD_DBID);
Dispatcher->LockQueue();
- for(unsigned int i = qq.size() - 1; i >= 0; i--)
+ unsigned int i = qq.size();
+ while (i > 0)
{
+ i--;
if (qq[i].q->creator == mod)
{
if (i == 0)
QQueueItem i = Parent->qq.front();
i.c->lock.Lock();
this->UnlockQueue();
- MySQLresult* res = i.c->DoBlockingQuery(i.q);
+ MySQLresult* res = i.c->DoBlockingQuery(i.query);
i.c->lock.Unlock();
/*
*/
this->LockQueue();
- if (Parent->qq.front().q == i.q)
+ if (!Parent->qq.empty() && Parent->qq.front().q == i.q)
{
Parent->qq.pop_front();
Parent->rq.push_back(RQueueItem(i.q, res));