summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-12-13 06:12:56 -0500
committerAdam <Adam@anope.org>2012-12-13 06:12:56 -0500
commitc1077faa281c5635f85b892e605e23bd6c8fcc3b (patch)
tree213b5f87a19f182e1efd6110f03ff10d5b10ebf6 /modules
parent76ba147c22944b67e8522cd2bb7b6e1bae498ced (diff)
Optimize much of the database code and serialize code.
Diffstat (limited to 'modules')
-rw-r--r--modules/commands/cs_entrymsg.cpp18
-rw-r--r--modules/commands/cs_fantasy_stats.cpp32
-rw-r--r--modules/commands/cs_fantasy_top.cpp32
-rw-r--r--modules/commands/cs_seen.cpp14
-rw-r--r--modules/commands/cs_set_misc.cpp18
-rw-r--r--modules/commands/cs_suspend.cpp12
-rw-r--r--modules/commands/hs_request.cpp13
-rw-r--r--modules/commands/ns_ajoin.cpp14
-rw-r--r--modules/commands/ns_set_misc.cpp18
-rw-r--r--modules/commands/ns_suspend.cpp12
-rw-r--r--modules/commands/os_dns.cpp12
-rw-r--r--modules/commands/os_forbid.h8
-rw-r--r--modules/commands/os_ignore.h15
-rw-r--r--modules/commands/os_news.h8
-rw-r--r--modules/commands/os_oper.cpp15
-rw-r--r--modules/commands/os_session.h8
-rw-r--r--modules/commands/os_stats.cpp6
-rw-r--r--modules/database/db_flatfile.cpp354
-rw-r--r--modules/database/db_sql.cpp62
-rw-r--r--modules/database/db_sql_live.cpp48
-rw-r--r--modules/extra/m_chanstats.cpp58
-rw-r--r--modules/extra/m_mysql.cpp96
-rw-r--r--modules/extra/m_sql_authentication.cpp28
-rw-r--r--modules/extra/m_sql_oper.cpp22
-rw-r--r--modules/extra/m_sqlite.cpp76
-rw-r--r--modules/extra/sql.h280
-rw-r--r--modules/extra/webcpanel/pages/chanserv/access.cpp2
27 files changed, 738 insertions, 543 deletions
diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp
index 85e428cc1..ab9c4d0c4 100644
--- a/modules/commands/cs_entrymsg.cpp
+++ b/modules/commands/cs_entrymsg.cpp
@@ -28,16 +28,12 @@ struct EntryMsg : Serializable
this->when = ct;
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["ci"] << this->ci->name;
data["creator"] << this->creator;
data["message"] << this->message;
- data["when"].SetType(Serialize::DT_INT) << this->when;
-
- return data;
+ data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
@@ -52,7 +48,13 @@ struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >, Extensib
Serializable* EntryMsg::Unserialize(Serializable *obj, Serialize::Data &data)
{
- ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
+ Anope::string sci, screator, smessage;
+
+ data["ci"] >> sci;
+ data["creator"] >> screator;
+ data["message"] >> smessage;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
if (!ci)
return NULL;
@@ -73,7 +75,7 @@ Serializable* EntryMsg::Unserialize(Serializable *obj, Serialize::Data &data)
ci->Extend("cs_entrymsg", messages);
}
- EntryMsg *m = new EntryMsg(ci, data["creator"].astr(), data["message"].astr());
+ EntryMsg *m = new EntryMsg(ci, screator, smessage);
(*messages)->push_back(m);
return m;
}
diff --git a/modules/commands/cs_fantasy_stats.cpp b/modules/commands/cs_fantasy_stats.cpp
index bbe135298..5b25cccce 100644
--- a/modules/commands/cs_fantasy_stats.cpp
+++ b/modules/commands/cs_fantasy_stats.cpp
@@ -14,16 +14,16 @@
#include "module.h"
#include "../extra/sql.h"
-class MySQLInterface : public SQLInterface
+class MySQLInterface : public SQL::Interface
{
public:
- MySQLInterface(Module *o) : SQLInterface(o) { }
+ MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const SQL::Result &r) anope_override
{
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const SQL::Result &r) anope_override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -66,7 +66,7 @@ class CSStats : public Module
{
CommandCSStats commandcsstats;
CommandCSGStats commandcsgstats;
- ServiceReference<SQLProvider> sql;
+ ServiceReference<SQL::Provider> sql;
MySQLInterface sqlinterface;
Anope::string prefix;
public:
@@ -86,17 +86,17 @@ class CSStats : public Module
ConfigReader config;
prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
- this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
+ this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
}
- SQLResult RunQuery(const SQLQuery &query)
+ SQL::Result RunQuery(const SQL::Query &query)
{
if (!this->sql)
- throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+ throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
- SQLResult res = this->sql->RunQuery(query);
+ SQL::Result res = this->sql->RunQuery(query);
if (!res.GetError().empty())
- throw SQLException(res.GetError());
+ throw SQL::Exception(res.GetError());
return res;
}
@@ -118,16 +118,16 @@ class CSStats : public Module
try
{
- SQLQuery query;
+ SQL::Query query;
query = "SELECT letters, words, line, smileys_happy+smileys_sad+smileys_other as smileys,"
"actions FROM `" + prefix + "chanstats` "
"WHERE `nick` = @nick@ AND `chan` = @channel@ AND `type` = 'total';";
if (is_global)
- query.setValue("channel", "");
+ query.SetValue("channel", "");
else
- query.setValue("channel", source.c->ci->name);
- query.setValue("nick", display);
- SQLResult res = this->RunQuery(query);
+ query.SetValue("channel", source.c->ci->name);
+ query.SetValue("nick", display);
+ SQL::Result res = this->RunQuery(query);
if (res.Rows() > 0)
{
@@ -144,7 +144,7 @@ class CSStats : public Module
else
source.Reply(_("No stats for %s"), display.c_str());
}
- catch (const SQLException &ex)
+ catch (const SQL::Exception &ex)
{
Log(LOG_DEBUG) << ex.GetReason();
}
diff --git a/modules/commands/cs_fantasy_top.cpp b/modules/commands/cs_fantasy_top.cpp
index 86e25f122..ca9572039 100644
--- a/modules/commands/cs_fantasy_top.cpp
+++ b/modules/commands/cs_fantasy_top.cpp
@@ -14,16 +14,16 @@
#include "module.h"
#include "../extra/sql.h"
-class MySQLInterface : public SQLInterface
+class MySQLInterface : public SQL::Interface
{
public:
- MySQLInterface(Module *o) : SQLInterface(o) { }
+ MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const SQL::Result &r) anope_override
{
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const SQL::Result &r) anope_override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -93,7 +93,7 @@ class CSTop : public Module
CommandCSGTop commandcsgtop;
CommandCSTop10 commandcstop10;
CommandCSGTop10 commandcsgtop10;
- ServiceReference<SQLProvider> sql;
+ ServiceReference<SQL::Provider> sql;
MySQLInterface sqlinterface;
Anope::string prefix;
@@ -115,17 +115,17 @@ class CSTop : public Module
ConfigReader config;
prefix = config.ReadValue("chanstats", "prefix", "anope_", 0);
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
- this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
+ this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
}
- SQLResult RunQuery(const SQLQuery &query)
+ SQL::Result RunQuery(const SQL::Query &query)
{
if (!this->sql)
- throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+ throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
- SQLResult res = sql->RunQuery(query);
+ SQL::Result res = sql->RunQuery(query);
if (!res.GetError().empty())
- throw SQLException(res.GetError());
+ throw SQL::Exception(res.GetError());
return res;
}
@@ -147,20 +147,20 @@ class CSTop : public Module
try
{
- SQLQuery query;
+ SQL::Query query;
query = "SELECT nick, letters, words, line, actions,"
"smileys_happy+smileys_sad+smileys_other as smileys "
"FROM `" + prefix + "chanstats` "
"WHERE `nick` != '' AND `chan` = @channel@ AND `type` = 'total' "
"ORDER BY `letters` DESC LIMIT @limit@;";
- query.setValue("limit", limit, false);
+ query.SetValue("limit", limit, false);
if (is_global)
- query.setValue("channel", "");
+ query.SetValue("channel", "");
else
- query.setValue("channel", channel.c_str());
+ query.SetValue("channel", channel.c_str());
- SQLResult res = this->RunQuery(query);
+ SQL::Result res = this->RunQuery(query);
if (res.Rows() > 0)
{
@@ -176,7 +176,7 @@ class CSTop : public Module
else
source.Reply(_("No stats for %s"), is_global ? "Network" : channel.c_str());
}
- catch (const SQLException &ex)
+ catch (const SQL::Exception &ex)
{
Log(LOG_DEBUG) << ex.GetReason();
}
diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp
index 18a21d35e..8f90e2f08 100644
--- a/modules/commands/cs_seen.cpp
+++ b/modules/commands/cs_seen.cpp
@@ -38,30 +38,30 @@ struct SeenInfo : Serializable
{
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["nick"] << nick;
data["vhost"] << vhost;
data["type"] << type;
data["nick2"] << nick2;
data["channel"] << channel;
data["message"] << message;
- data["last"].SetType(Serialize::DT_INT) << last;
-
- return data;
+ data.SetType("last", Serialize::Data::DT_INT); data["last"] << last;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
{
+ Anope::string snick;
+
+ data["nick"] >> snick;
+
SeenInfo *s;
if (obj)
s = anope_dynamic_static_cast<SeenInfo *>(obj);
else
{
/* ignore duplicate entries in the db, created by an old bug */
- s = FindInfo(data["nick"].str());
+ s = FindInfo(snick);
if (!s)
s = new SeenInfo();
}
diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp
index 3bf0e9bbd..1fb25c79a 100644
--- a/modules/commands/cs_set_misc.cpp
+++ b/modules/commands/cs_set_misc.cpp
@@ -22,20 +22,22 @@ struct CSMiscData : ExtensibleItem, Serializable
{
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &sdata) const anope_override
{
- Serialize::Data sdata;
-
sdata["ci"] << this->ci->name;
sdata["name"] << this->name;
sdata["data"] << this->data;
-
- return sdata;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
{
- ChannelInfo *ci = ChannelInfo::Find(data["ci"].astr());
+ Anope::string sci, sname, sdata;
+
+ data["ci"] >> sci;
+ data["name"] >> sname;
+ data["data"] >> sdata;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
if (ci == NULL)
return NULL;
@@ -49,8 +51,8 @@ struct CSMiscData : ExtensibleItem, Serializable
}
else
{
- d = new CSMiscData(ci, data["name"].astr(), data["data"].astr());
- ci->Extend(data["name"].astr(), d);
+ d = new CSMiscData(ci, sname, sdata);
+ ci->Extend(sname, d);
}
return d;
diff --git a/modules/commands/cs_suspend.cpp b/modules/commands/cs_suspend.cpp
index b380d4c97..097de1823 100644
--- a/modules/commands/cs_suspend.cpp
+++ b/modules/commands/cs_suspend.cpp
@@ -22,19 +22,19 @@ struct ChanSuspend : ExtensibleItem, Serializable
{
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &sd) const anope_override
{
- Serialize::Data sd;
-
sd["chan"] << this->chan;
sd["when"] << this->when;
-
- return sd;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
{
- ChannelInfo *ci = ChannelInfo::Find(sd["chan"].astr());
+ Anope::string schan;
+
+ sd["chan"] >> schan;
+
+ ChannelInfo *ci = ChannelInfo::Find(schan);
if (ci == NULL)
return NULL;
diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp
index c7cd75c11..6cd2e6811 100644
--- a/modules/commands/hs_request.cpp
+++ b/modules/commands/hs_request.cpp
@@ -32,21 +32,20 @@ struct HostRequest : ExtensibleItem, Serializable
HostRequest() : Serializable("HostRequest") { }
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["nick"] << this->nick;
data["ident"] << this->ident;
data["host"] << this->host;
- data["time"].SetType(Serialize::DT_INT) << this->time;
-
- return data;
+ data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
{
- NickAlias *na = NickAlias::Find(data["nick"].astr());
+ Anope::string snick;
+ data["nick"] >> snick;
+
+ NickAlias *na = NickAlias::Find(snick);
if (na == NULL)
return NULL;
diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp
index ce92582f6..3a73772c1 100644
--- a/modules/commands/ns_ajoin.cpp
+++ b/modules/commands/ns_ajoin.cpp
@@ -28,23 +28,23 @@ struct AJoinEntry : Serializable
AJoinEntry() : Serializable("AJoinEntry") { }
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &sd) const anope_override
{
- Serialize::Data sd;
-
if (!this->owner)
- return sd;
+ return;
sd["owner"] << this->owner->display;
sd["channel"] << this->channel;
sd["key"] << this->key;
-
- return sd;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
{
- NickCore *nc = NickCore::Find(sd["owner"].astr());
+ Anope::string sowner;
+
+ sd["owner"] >> sowner;
+
+ NickCore *nc = NickCore::Find(sowner);
if (nc == NULL)
return NULL;
diff --git a/modules/commands/ns_set_misc.cpp b/modules/commands/ns_set_misc.cpp
index 1e088a425..b6dd672a3 100644
--- a/modules/commands/ns_set_misc.cpp
+++ b/modules/commands/ns_set_misc.cpp
@@ -23,20 +23,22 @@ struct NSMiscData : ExtensibleItem, Serializable
{
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &sdata) const anope_override
{
- Serialize::Data sdata;
-
sdata["nc"] << this->nc->display;
sdata["name"] << this->name;
sdata["data"] << this->data;
-
- return sdata;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
{
- NickCore *nc = NickCore::Find(data["nc"].astr());
+ Anope::string snc, sname, sdata;
+
+ data["nc"] >> snc;
+ data["name"] >> sname;
+ data["data"] >> sdata;
+
+ NickCore *nc = NickCore::Find(snc);
if (nc == NULL)
return NULL;
@@ -50,8 +52,8 @@ struct NSMiscData : ExtensibleItem, Serializable
}
else
{
- d = new NSMiscData(nc, data["name"].astr(), data["data"].astr());
- nc->Extend(data["name"].astr(), d);
+ d = new NSMiscData(nc, sname, sdata);
+ nc->Extend(sname, d);
}
return d;
diff --git a/modules/commands/ns_suspend.cpp b/modules/commands/ns_suspend.cpp
index 6ff355437..63710ccca 100644
--- a/modules/commands/ns_suspend.cpp
+++ b/modules/commands/ns_suspend.cpp
@@ -22,19 +22,19 @@ struct NickSuspend : ExtensibleItem, Serializable
{
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &sd) const anope_override
{
- Serialize::Data sd;
-
sd["nick"] << this->nick;
sd["when"] << this->when;
-
- return sd;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
{
- const NickAlias *na = NickAlias::Find(sd["nick"].astr());
+ Anope::string snick;
+
+ sd["nick"] >> snick;
+
+ const NickAlias *na = NickAlias::Find(snick);
if (na == NULL)
return NULL;
diff --git a/modules/commands/os_dns.cpp b/modules/commands/os_dns.cpp
index 769a42f26..6e5689396 100644
--- a/modules/commands/os_dns.cpp
+++ b/modules/commands/os_dns.cpp
@@ -49,17 +49,13 @@ class DNSServer : public Serializable
}
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["server_name"] << server_name;
for (unsigned i = 0; i < ips.size(); ++i)
data["ip" + stringify(i)] << ips[i];
data["limit"] << limit;
data["pooled"] << pooled;
-
- return data;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
@@ -72,12 +68,16 @@ class DNSServer : public Serializable
req = new DNSServer();
data["server_name"] >> req->server_name;
- for (unsigned i = 0; data.count("ip" + stringify(i)); ++i)
+
+ for (unsigned i = 0; true; ++i)
{
Anope::string ip_str;
data["ip" + stringify(i)] >> ip_str;
+ if (ip_str.empty())
+ break;
req->ips.push_back(ip_str);
}
+
data["limit"] >> req->limit;
data["pooled"] >> req->pooled;
diff --git a/modules/commands/os_forbid.h b/modules/commands/os_forbid.h
index 1fce928db..07619f65e 100644
--- a/modules/commands/os_forbid.h
+++ b/modules/commands/os_forbid.h
@@ -19,7 +19,7 @@ struct ForbidData : Serializable
ForbidType type;
ForbidData() : Serializable("ForbidData") { }
- Serialize::Data Serialize() const anope_override;
+ void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
@@ -39,18 +39,14 @@ class ForbidService : public Service
static ServiceReference<ForbidService> forbid_service("ForbidService", "forbid");
-Serialize::Data ForbidData::Serialize() const
+void ForbidData::Serialize(Serialize::Data &data) const
{
- Serialize::Data data;
-
data["mask"] << this->mask;
data["creator"] << this->creator;
data["reason"] << this->reason;
data["created"] << this->created;
data["expires"] << this->expires;
data["type"] << this->type;
-
- return data;
}
Serializable* ForbidData::Unserialize(Serializable *obj, Serialize::Data &data)
diff --git a/modules/commands/os_ignore.h b/modules/commands/os_ignore.h
index 003d88b5b..1990d95c4 100644
--- a/modules/commands/os_ignore.h
+++ b/modules/commands/os_ignore.h
@@ -18,7 +18,7 @@ struct IgnoreData : Serializable
time_t time; /* When do we stop ignoring them? */
IgnoreData() : Serializable("IgnoreData") { }
- Serialize::Data Serialize() const anope_override;
+ void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
@@ -43,16 +43,12 @@ class IgnoreService : public Service
static ServiceReference<IgnoreService> ignore_service("IgnoreService", "ignore");
-Serialize::Data IgnoreData::Serialize() const
+void IgnoreData::Serialize(Serialize::Data &data) const
{
- Serialize::Data data;
-
data["mask"] << this->mask;
data["creator"] << this->creator;
data["reason"] << this->reason;
data["time"] << this->time;
-
- return data;
}
Serializable* IgnoreData::Unserialize(Serializable *obj, Serialize::Data &data)
@@ -70,9 +66,14 @@ Serializable* IgnoreData::Unserialize(Serializable *obj, Serialize::Data &data)
return ign;
}
+ Anope::string smask, screator, sreason;
time_t t;
+
+ data["mask"] >> smask;
+ data["creator"] >> screator;
+ data["reason"] >> sreason;
data["time"] >> t;
- return ignore_service->AddIgnore(data["mask"].astr(), data["creator"].astr(), data["reason"].astr(), t);
+ return ignore_service->AddIgnore(smask, screator, sreason, t);
}
diff --git a/modules/commands/os_news.h b/modules/commands/os_news.h
index 44525b963..b1e717455 100644
--- a/modules/commands/os_news.h
+++ b/modules/commands/os_news.h
@@ -23,7 +23,7 @@ struct NewsItem : Serializable
time_t time;
NewsItem() : Serializable("NewsItem") { }
- Serialize::Data Serialize() const anope_override;
+ void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
@@ -41,16 +41,12 @@ class NewsService : public Service
static ServiceReference<NewsService> news_service("NewsService", "news");
-Serialize::Data NewsItem::Serialize() const
+void NewsItem::Serialize(Serialize::Data &data) const
{
- Serialize::Data data;
-
data["type"] << this->type;
data["text"] << this->text;
data["who"] << this->who;
data["time"] << this->time;
-
- return data;
}
Serializable* NewsItem::Unserialize(Serializable *obj, Serialize::Data &data)
diff --git a/modules/commands/os_oper.cpp b/modules/commands/os_oper.cpp
index 882455898..b014a1271 100644
--- a/modules/commands/os_oper.cpp
+++ b/modules/commands/os_oper.cpp
@@ -17,22 +17,23 @@ struct MyOper : Oper, Serializable
{
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["name"] << this->name;
data["type"] << this->ot->GetName();
-
- return data;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
{
- OperType *ot = OperType::Find(data["type"].astr());
+ Anope::string stype, sname;
+
+ data["type"] >> stype;
+ data["name"] >> sname;
+
+ OperType *ot = OperType::Find(stype);
if (ot == NULL)
return NULL;
- NickCore *nc = NickCore::Find(data["name"].astr());
+ NickCore *nc = NickCore::Find(sname);
if (nc == NULL)
return NULL;
diff --git a/modules/commands/os_session.h b/modules/commands/os_session.h
index 7304b21ae..6d1dd917d 100644
--- a/modules/commands/os_session.h
+++ b/modules/commands/os_session.h
@@ -20,7 +20,7 @@ struct Exception : Serializable
time_t expires; /* Time when it expires. 0 == no expiry */
Exception() : Serializable("Exception") { }
- Serialize::Data Serialize() const anope_override;
+ void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
@@ -53,18 +53,14 @@ class SessionService : public Service
static ServiceReference<SessionService> session_service("SessionService", "session");
-Serialize::Data Exception::Serialize() const
+void Exception::Serialize(Serialize::Data &data) const
{
- Serialize::Data data;
-
data["mask"] << this->mask;
data["limit"] << this->limit;
data["who"] << this->who;
data["reason"] << this->reason;
data["time"] << this->time;
data["expires"] << this->expires;
-
- return data;
}
Serializable* Exception::Unserialize(Serializable *obj, Serialize::Data &data)
diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp
index bb029eed9..18e2e89fd 100644
--- a/modules/commands/os_stats.cpp
+++ b/modules/commands/os_stats.cpp
@@ -18,14 +18,10 @@ struct Stats : Serializable
{
Stats() : Serializable("Stats") { }
- Serialize::Data Serialize() const anope_override
+ void Serialize(Serialize::Data &data) const anope_override
{
- Serialize::Data data;
-
data["maxusercnt"] << MaxUserCount;
data["maxusertime"] << MaxUserTime;
-
- return data;
}
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp
index acb287cee..66715b9f8 100644
--- a/modules/database/db_flatfile.cpp
+++ b/modules/database/db_flatfile.cpp
@@ -12,145 +12,202 @@
#include "module.h"
-class DBFlatFile : public Module
+class SaveData : public Serialize::Data
{
- Anope::string DatabaseFile;
- Anope::string BackupFile;
- /* Day the last backup was on */
- int LastDay;
- /* Backup file names */
- std::list<Anope::string> Backups;
+ public:
+ std::fstream *fs;
+
+ SaveData() : fs(NULL) { }
+
+ std::iostream& operator[](const Anope::string &key) anope_override
+ {
+ *fs << "\nDATA " << key << " ";
+ return *fs;
+ }
+};
+class LoadData : public Serialize::Data
+{
public:
- DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE)
+ std::fstream *fs;
+ std::map<Anope::string, Anope::string> data;
+ std::stringstream ss;
+ bool read;
+
+ LoadData() : fs(NULL), read(false) { }
+
+ std::iostream& operator[](const Anope::string &key) anope_override
{
- this->SetAuthor("Anope");
+ if (!read)
+ {
+ for (Anope::string token; std::getline(*this->fs, token.str());)
+ {
+ if (token.find("DATA ") != 0)
+ break;
- Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase };
- ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
+ size_t sp = token.find(' ', 5); // Skip DATA
+ if (sp != Anope::string::npos)
+ data[token.substr(5, sp - 5)] = token.substr(sp + 1);
+ }
- OnReload();
+ read = true;
+ }
- LastDay = 0;
+ ss.clear();
+ this->ss << this->data[key];
+ return this->ss;
}
+
+ void Reset()
+ {
+ read = false;
+ data.clear();
+ }
+};
+
+class DBFlatFile : public Module, public Pipe
+{
+ Anope::string database_file;
+ /* Day the last backup was on */
+ int last_day;
+ /* Backup file names */
+ std::map<Anope::string, std::list<Anope::string> > backups;
+ bool use_fork;
void BackupDatabase()
{
- /* Do not backup a database that doesn't exist */
- if (!Anope::IsFile(DatabaseFile))
- return;
-
- time_t now = Anope::CurTime;
- tm *tm = localtime(&now);
+ tm *tm = localtime(&Anope::CurTime);
- if (tm->tm_mday != LastDay)
+ if (tm->tm_mday != last_day)
{
- LastDay = tm->tm_mday;
- Anope::string newname = BackupFile + "." + stringify(tm->tm_year) + "." + stringify(tm->tm_mon) + "." + stringify(tm->tm_mday);
+ last_day = tm->tm_mday;
- /* Backup already exists */
- if (IsFile(newname))
- return;
+ const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
- Log(LOG_DEBUG) << "db_flatfile: Attemping to rename " << DatabaseFile << " to " << newname;
- if (rename(DatabaseFile.c_str(), newname.c_str()))
- {
- Log(this) << "Unable to back up database!";
+ std::set<Anope::string> dbs;
+ dbs.insert(database_file);
- if (!Config->NoBackupOkay)
- Anope::Quitting = true;
+ for (unsigned i = 0; i < type_order.size(); ++i)
+ {
+ Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
- return;
+ if (stype && stype->GetOwner())
+ dbs.insert("module_" + stype->GetOwner()->name + ".db");
}
- Backups.push_back(newname);
- if (Config->KeepBackups > 0 && Backups.size() > static_cast<unsigned>(Config->KeepBackups))
+ for (std::set<Anope::string>::const_iterator it = dbs.begin(), it_end = dbs.end(); it != it_end; ++it)
{
- unlink(Backups.front().c_str());
- Backups.pop_front();
+ const Anope::string &oldname = Anope::DataDir + "/" + *it;
+ Anope::string newname = Anope::DataDir + "/backups/" + *it + "." + stringify(tm->tm_year) + "." + stringify(tm->tm_mon) + "." + stringify(tm->tm_mday);
+
+ /* Backup already exists */
+ if (Anope::IsFile(newname))
+ continue;
+
+ Log(LOG_DEBUG) << "db_flatfile: Attemping to rename " << *it << " to " << newname;
+ if (rename(oldname.c_str(), newname.c_str()))
+ {
+ Log(this) << "Unable to back up database " << *it << "!";
+
+ if (!Config->NoBackupOkay)
+ Anope::Quitting = true;
+
+ continue;
+ }
+
+ backups[*it].push_back(newname);
+
+ if (Config->KeepBackups > 0 && backups[*it].size() > static_cast<unsigned>(Config->KeepBackups))
+ {
+ unlink(backups[*it].front().c_str());
+ backups[*it].pop_front();
+ }
}
}
}
- void OnReload() anope_override
+ public:
+ DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), last_day(0), use_fork(false)
{
- ConfigReader config;
- DatabaseFile = Anope::DataDir + "/" + config.ReadValue("db_flatfile", "database", "anope.db", 0);
- BackupFile = Anope::DataDir + "/backups/" + config.ReadValue("db_flatfile", "database", "anope.db", 0);
+ this->SetAuthor("Anope");
+
+ Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase };
+ ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
+
+ OnReload();
}
- EventReturn OnLoadDatabase() anope_override
+ void OnNotify() anope_override
{
- std::map<Module *, std::fstream *> databases;
- databases[NULL] = new std::fstream(DatabaseFile.c_str(), std::ios_base::in);
+ char buf[512];
+ int i = this->Read(buf, sizeof(buf) - 1);
+ if (i <= 0)
+ return;
+ buf[i] = 0;
- if (!databases[NULL]->is_open())
+ if (!*buf)
{
- delete databases[NULL];
- Log(this) << "Unable to open " << DatabaseFile << " for reading!";
- return EVENT_CONTINUE;
+ Log(this) << "Finished saving databases";
+ return;
}
- const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
+ Log(this) << "Error saving databases: " << buf;
- for (unsigned i = 0; i < type_order.size(); ++i)
- {
- Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
- if (stype && !databases.count(stype->GetOwner()))
- {
- Anope::string db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
- databases[stype->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::in);
- }
- }
+ if (!Config->NoBackupOkay)
+ Anope::Quitting = true;
+ }
- std::multimap<Serialize::Type *, Serialize::Data> objects;
- for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
- {
- std::fstream *db = it->second;
- Serialize::Type *st = NULL;
- Serialize::Data data;
- for (Anope::string buf, token; std::getline(*db, buf.str());)
- {
- spacesepstream sep(buf);
+ void OnReload() anope_override
+ {
+ ConfigReader config;
+ database_file = config.ReadValue("db_flatfile", "database", "anope.db", 0);
+ use_fork = config.ReadFlag("db_flatfile", "fork", "no", 0);
+ }
- if (!sep.GetToken(token))
- continue;
+ EventReturn OnLoadDatabase() anope_override
+ {
+ const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
+ std::set<Anope::string> tried_dbs;
- if (token == "OBJECT" && sep.GetToken(token))
- {
- st = Serialize::Type::Find(token);
- data.clear();
- }
- else if (token == "DATA" && st != NULL && sep.GetToken(token))
- data[token] << sep.GetRemaining();
- else if (token == "END" && st != NULL)
- {
- objects.insert(std::make_pair(st, data));
+ const Anope::string &db_name = Anope::DataDir + "/" + database_file;
- st = NULL;
- data.clear();
- }
- }
+ std::fstream fd(db_name.c_str(), std::ios_base::in);
+ if (!fd.is_open())
+ {
+ Log(this) << "Unable to open " << db_name << " for reading!";
+ return EVENT_STOP;
}
+ std::map<Anope::string, std::vector<std::streampos> > positions;
+
+ for (Anope::string buf; std::getline(fd, buf.str());)
+ if (buf.find("OBJECT ") == 0)
+ positions[buf.substr(7)].push_back(fd.tellg());
+
+ LoadData ld;
+ ld.fs = &fd;
+
for (unsigned i = 0; i < type_order.size(); ++i)
{
Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
-
- std::multimap<Serialize::Type *, Serialize::Data>::iterator it = objects.find(stype), it_end = objects.upper_bound(stype);
- if (it == objects.end())
+ if (!stype || stype->GetOwner())
continue;
- for (; it != it_end; ++it)
- it->first->Unserialize(NULL, it->second);
- }
+
+ std::vector<std::streampos> &pos = positions[stype->GetName()];
- for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
- {
- it->second->close();
- delete it->second;
+ for (unsigned j = 0; j < pos.size(); ++j)
+ {
+ fd.clear();
+ fd.seekg(pos[j]);
+
+ stype->Unserialize(NULL, ld);
+ ld.Reset();
+ }
}
+ fd.close();
+
return EVENT_STOP;
}
@@ -159,61 +216,92 @@ class DBFlatFile : public Module
{
BackupDatabase();
- Anope::string tmp_db = DatabaseFile + ".tmp";
- if (IsFile(DatabaseFile))
- rename(DatabaseFile.c_str(), tmp_db.c_str());
-
- std::map<Module *, std::fstream *> databases;
- databases[NULL] = new std::fstream(DatabaseFile.c_str(), std::ios_base::out | std::ios_base::trunc);
- if (!databases[NULL]->is_open())
+ int i = -1;
+ if (use_fork)
{
- delete databases[NULL];
- Log(this) << "Unable to open " << DatabaseFile << " for writing";
- if (IsFile(tmp_db))
- rename(tmp_db.c_str(), DatabaseFile.c_str());
- return EVENT_CONTINUE;
+ i = fork();
+ if (i > 0)
+ return EVENT_CONTINUE;
+ else if (i < 0)
+ Log(this) << "Unable to fork for database save";
}
- const std::list<Serializable *> &items = Serializable::GetItems();
- for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
+ try
{
- Serializable *base = *it;
- Serialize::Type *s_type = base->GetSerializableType();
+ std::map<Module *, std::fstream *> databases;
- if (!s_type)
- continue;
+ SaveData data;
+ const std::list<Serializable *> &items = Serializable::GetItems();
+ for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
+ {
+ Serializable *base = *it;
+ Serialize::Type *s_type = base->GetSerializableType();
+
+ if (!s_type)
+ continue;
- Serialize::Data data = base->Serialize();
+ data.fs = databases[s_type->GetOwner()];
- if (!databases.count(s_type->GetOwner()))
+ if (!data.fs)
+ {
+ Anope::string db_name;
+ if (s_type->GetOwner())
+ db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
+ else
+ db_name = Anope::DataDir + "/" + database_file;
+
+ if (Anope::IsFile(db_name))
+ rename(db_name.c_str(), (db_name + ".tmp").c_str());
+
+ data.fs = databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc);
+
+ if (!data.fs->is_open())
+ {
+ Log(this) << "Unable to open " << db_name << " for writing";
+ continue;
+ }
+ }
+ else if (!data.fs->is_open())
+ continue;
+
+ *data.fs << "OBJECT " << s_type->GetName();
+ base->Serialize(data);
+ *data.fs << "\nEND\n";
+ }
+
+ for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
{
- Anope::string db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
- databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc);
+ std::fstream *f = it->second;
+ const Anope::string &db_name = Anope::DataDir + "/" + (it->first ? (it->first->name + ".db") : database_file);
+
+ if (!f->is_open() || !f->good())
+ {
+ this->Write("Unable to write database " + db_name);
+
+ f->close();
+
+ if (Anope::IsFile((db_name + ".tmp").c_str()))
+ rename((db_name + ".tmp").c_str(), db_name.c_str());
+ }
+ else
+ {
+ f->close();
+ unlink((db_name + ".tmp").c_str());
+ }
+
+ delete f;
}
- std::fstream *fd = databases[s_type->GetOwner()];
-
- *fd << "OBJECT " << s_type->GetName() << "\n";
- for (Serialize::Data::iterator dit = data.begin(), dit_end = data.end(); dit != dit_end; ++dit)
- *fd << "DATA " << dit->first << " " << dit->second.astr() << "\n";
- *fd << "END\n";
}
-
- if (databases[NULL]->good() == false)
+ catch (...)
{
- Log(this) << "Unable to write database";
- databases[NULL]->close();
- if (!Config->NoBackupOkay)
- Anope::Quitting = true;
- if (IsFile(tmp_db))
- rename(tmp_db.c_str(), DatabaseFile.c_str());
+ if (i)
+ throw;
}
- else
- unlink(tmp_db.c_str());
- for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
+ if (!i)
{
- it->second->close();
- delete it->second;
+ this->Notify();
+ exit(0);
}
return EVENT_CONTINUE;
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp
index 60db11c0d..56db7b8a0 100644
--- a/modules/database/db_sql.cpp
+++ b/modules/database/db_sql.cpp
@@ -11,18 +11,19 @@
#include "module.h"
#include "../extra/sql.h"
-class SQLSQLInterface : public SQLInterface
+using namespace SQL;
+
+class SQLSQLInterface : public Interface
{
public:
- SQLSQLInterface(Module *o) : SQLInterface(o) { }
- virtual ~SQLSQLInterface() { }
+ SQLSQLInterface(Module *o) : Interface(o) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const Result &r) anope_override
{
Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const Result &r) anope_override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
@@ -38,7 +39,7 @@ class ResultSQLSQLInterface : public SQLSQLInterface
public:
ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const Result &r) anope_override
{
SQLSQLInterface::OnResult(r);
if (r.GetID() > 0 && this->obj)
@@ -46,7 +47,7 @@ public:
delete this;
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const Result &r) anope_override
{
SQLSQLInterface::OnError(r);
delete this;
@@ -55,13 +56,14 @@ public:
class DBSQL : public Module, public Pipe
{
- ServiceReference<SQLProvider> sql;
+ ServiceReference<Provider> sql;
SQLSQLInterface sqlinterface;
Anope::string prefix;
std::set<Reference<Serializable> > updated_items;
bool shutting_down;
+ bool loading_databases;
- void RunBackground(const SQLQuery &q, SQLInterface *iface = NULL)
+ void RunBackground(const Query &q, Interface *iface = NULL)
{
if (!this->sql)
{
@@ -83,7 +85,7 @@ class DBSQL : public Module, public Pipe
}
public:
- DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), shutting_down(false)
+ DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql("", ""), sqlinterface(this), shutting_down(false), loading_databases(false)
{
this->SetAuthor("Anope");
@@ -101,21 +103,26 @@ class DBSQL : public Module, public Pipe
if (obj && this->sql)
{
- if (obj->IsCached())
+ Data *data = new Data();
+ obj->Serialize(*data);
+
+ if (obj->IsCached(data))
+ {
+ delete data;
continue;
- obj->UpdateCache();
+ }
+
+ obj->UpdateCache(data);
Serialize::Type *s_type = obj->GetSerializableType();
if (!s_type)
continue;
- Serialize::Data data = obj->Serialize();
-
- std::vector<SQLQuery> create = this->sql->CreateTable(this->prefix + s_type->GetName(), data);
+ std::vector<Query> create = this->sql->CreateTable(this->prefix + s_type->GetName(), *data);
for (unsigned i = 0; i < create.size(); ++i)
this->RunBackground(create[i]);
- SQLQuery insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data);
+ Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, *data);
this->RunBackground(insert, new ResultSQLSQLInterface(this, obj));
}
}
@@ -127,7 +134,7 @@ class DBSQL : public Module, public Pipe
{
ConfigReader config;
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
- this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
+ this->sql = ServiceReference<Provider>("SQL::Provider", engine);
this->prefix = config.ReadValue("db_sql", "prefix", "anope_db_", 0);
}
@@ -150,23 +157,25 @@ class DBSQL : public Module, public Pipe
return EVENT_CONTINUE;
}
+ this->loading_databases = true;
+
const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
for (unsigned i = 0; i < type_order.size(); ++i)
{
Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
- SQLQuery query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
- SQLResult res = this->sql->RunQuery(query);
+ Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
+ Result res = this->sql->RunQuery(query);
for (int j = 0; j < res.Rows(); ++j)
{
- Serialize::Data data;
+ Data *data = new Data();
const std::map<Anope::string, Anope::string> &row = res.Row(j);
for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
- data[rit->first] << rit->second;
+ (*data)[rit->first] << rit->second;
- Serializable *obj = sb->Unserialize(NULL, data);
+ Serializable *obj = sb->Unserialize(NULL, *data);
try
{
if (obj)
@@ -176,15 +185,22 @@ class DBSQL : public Module, public Pipe
{
Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
}
+
+ if (obj)
+ obj->UpdateCache(data); /* We know this is the most up to date copy */
+ else
+ delete data;
}
}
+ this->loading_databases = false;
+
return EVENT_STOP;
}
void OnSerializableConstruct(Serializable *obj) anope_override
{
- if (this->shutting_down)
+ if (this->shutting_down || this->loading_databases)
return;
this->updated_items.insert(obj);
this->Notify();
diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp
index 00561592f..8d8836055 100644
--- a/modules/database/db_sql_live.cpp
+++ b/modules/database/db_sql_live.cpp
@@ -2,12 +2,14 @@
#include "../extra/sql.h"
#include "../commands/os_session.h"
+using namespace SQL;
+
class DBMySQL : public Module, public Pipe
{
private:
Anope::string engine;
Anope::string prefix;
- ServiceReference<SQLProvider> SQL;
+ ServiceReference<Provider> SQL;
time_t lastwarn;
bool ro;
bool init;
@@ -43,24 +45,24 @@ class DBMySQL : public Module, public Pipe
return init && SQL;
}
- void RunQuery(const SQLQuery &query)
+ void RunQuery(const Query &query)
{
/* Can this be threaded? */
this->RunQueryResult(query);
}
- SQLResult RunQueryResult(const SQLQuery &query)
+ Result RunQueryResult(const Query &query)
{
if (this->CheckSQL())
{
- SQLResult res = SQL->RunQuery(query);
+ Result res = SQL->RunQuery(query);
if (!res.GetError().empty())
Log(LOG_DEBUG) << "SQL-live got error " << res.GetError() << " for " + res.finished_query;
else
Log(LOG_DEBUG) << "SQL-live got " << res.Rows() << " rows for " << res.finished_query;
return res;
}
- throw SQLException("No SQL!");
+ throw SQL::Exception("No SQL!");
}
public:
@@ -87,21 +89,26 @@ class DBMySQL : public Module, public Pipe
if (obj && this->SQL)
{
- if (obj->IsCached())
+ Data *data = new Data();
+ obj->Serialize(*data);
+
+ if (obj->IsCached(data))
+ {
+ delete data;
continue;
- obj->UpdateCache();
+ }
+
+ obj->UpdateCache(data);
Serialize::Type *s_type = obj->GetSerializableType();
if (!s_type)
continue;
- Serialize::Data data = obj->Serialize();
-
- std::vector<SQLQuery> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
+ std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), *data);
for (unsigned i = 0; i < create.size(); ++i)
this->RunQueryResult(create[i]);
- SQLResult res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, data));
+ Result res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, *data));
if (obj->id != res.GetID())
{
/* In this case obj is new, so place it into the object map */
@@ -129,7 +136,7 @@ class DBMySQL : public Module, public Pipe
{
ConfigReader config;
this->engine = config.ReadValue("db_sql", "engine", "", 0);
- this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
+ this->SQL = ServiceReference<Provider>("SQL::Provider", this->engine);
this->prefix = config.ReadValue("db_sql", "prefix", "anope_db_", 0);
}
@@ -157,11 +164,11 @@ class DBMySQL : public Module, public Pipe
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
return;
- SQLQuery query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
+ Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
obj->UpdateTimestamp();
- SQLResult res = this->RunQueryResult(query);
+ Result res = this->RunQueryResult(query);
bool clear_null = false;
for (int i = 0; i < res.Rows(); ++i)
@@ -191,17 +198,17 @@ class DBMySQL : public Module, public Pipe
}
else
{
- Serialize::Data data;
+ Data *data = new Data();
for (std::map<Anope::string, Anope::string>::const_iterator it = row.begin(), it_end = row.end(); it != it_end; ++it)
- data[it->first] << it->second;
+ (*data)[it->first] << it->second;
Serializable *s = NULL;
std::map<unsigned int, Serializable *>::iterator it = obj->objects.find(id);
if (it != obj->objects.end())
s = it->second;
- Serializable *new_s = obj->Unserialize(s, data);
+ Serializable *new_s = obj->Unserialize(s, *data);
if (new_s)
{
// If s == new_s then s->id == new_s->id
@@ -209,11 +216,16 @@ class DBMySQL : public Module, public Pipe
{
new_s->id = id;
obj->objects[id] = new_s;
- new_s->UpdateCache(); /* We know this is the most up to date copy */
+ new_s->UpdateCache(data); /* We know this is the most up to date copy */
}
+ else
+ delete data;
}
else
+ {
+ delete data;
s->Destroy();
+ }
}
}
diff --git a/modules/extra/m_chanstats.cpp b/modules/extra/m_chanstats.cpp
index b50592b0f..7096b39a5 100644
--- a/modules/extra/m_chanstats.cpp
+++ b/modules/extra/m_chanstats.cpp
@@ -1,16 +1,16 @@
#include "module.h"
#include "../extra/sql.h"
-class MySQLInterface : public SQLInterface
+class MySQLInterface : public SQL::Interface
{
public:
- MySQLInterface(Module *o) : SQLInterface(o) { }
+ MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const SQL::Result &r) anope_override
{
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const SQL::Result &r) anope_override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -21,13 +21,13 @@ class MySQLInterface : public SQLInterface
class MChanstats : public Module
{
- ServiceReference<SQLProvider> sql;
+ ServiceReference<SQL::Provider> sql;
MySQLInterface sqlinterface;
- SQLQuery query;
+ SQL::Query query;
Anope::string SmileysHappy, SmileysSad, SmileysOther, prefix;
std::vector<Anope::string> TableList, ProcedureList, EventList;
- void RunQuery(const SQLQuery &q)
+ void RunQuery(const SQL::Query &q)
{
if (sql)
sql->Run(&sqlinterface, q);
@@ -70,7 +70,7 @@ class MChanstats : public Module
if (!sql)
return;
- SQLResult r = this->sql->RunQuery(this->sql->GetTables(prefix));
+ SQL::Result r = this->sql->RunQuery(this->sql->GetTables(prefix));
for (int i = 0; i < r.Rows(); ++i)
{
const std::map<Anope::string, Anope::string> &map = r.Row(i);
@@ -359,7 +359,7 @@ class MChanstats : public Module
SmileysOther = config.ReadValue("chanstats", "SmileysOther", ":/", 0);
Anope::string engine = config.ReadValue("chanstats", "engine", "", 0);
- this->sql = ServiceReference<SQLProvider>("SQLProvider", engine);
+ this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
if (sql)
this->CheckTables();
else
@@ -371,8 +371,8 @@ class MChanstats : public Module
if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS))
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
- query.setValue("channel", c->name);
- query.setValue("nick", GetDisplay(u));
+ query.SetValue("channel", c->name);
+ query.SetValue("nick", GetDisplay(u));
this->RunQuery(query);
}
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string &param) anope_override
@@ -392,8 +392,8 @@ class MChanstats : public Module
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
- query.setValue("channel", c->name);
- query.setValue("nick", GetDisplay(u));
+ query.SetValue("channel", c->name);
+ query.SetValue("nick", GetDisplay(u));
this->RunQuery(query);
}
public:
@@ -403,13 +403,13 @@ class MChanstats : public Module
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);";
- query.setValue("channel", c->name);
- query.setValue("nick", GetDisplay(target));
+ query.SetValue("channel", c->name);
+ query.SetValue("nick", GetDisplay(target));
this->RunQuery(query);
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);";
- query.setValue("channel", c->name);
- query.setValue("nick", GetDisplay(source.GetUser()));
+ query.SetValue("channel", c->name);
+ query.SetValue("nick", GetDisplay(source.GetUser()));
this->RunQuery(query);
}
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
@@ -437,33 +437,33 @@ class MChanstats : public Module
words = words - smileys_happy - smileys_sad - smileys_other;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 1, @letters@, @words@, @action@, "
"@smileys_happy@, @smileys_sad@, @smileys_other@, '0', '0', '0', '0');";
- query.setValue("channel", c->name);
- query.setValue("nick", GetDisplay(u));
- query.setValue("letters", letters);
- query.setValue("words", words);
- query.setValue("action", action);
- query.setValue("smileys_happy", smileys_happy);
- query.setValue("smileys_sad", smileys_sad);
- query.setValue("smileys_other", smileys_other);
+ query.SetValue("channel", c->name);
+ query.SetValue("nick", GetDisplay(u));
+ query.SetValue("letters", letters);
+ query.SetValue("words", words);
+ query.SetValue("action", action);
+ query.SetValue("smileys_happy", smileys_happy);
+ query.SetValue("smileys_sad", smileys_sad);
+ query.SetValue("smileys_other", smileys_other);
this->RunQuery(query);
}
void OnDelCore(NickCore *nc) anope_override
{
query = "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = @nick@;";
- query.setValue("nick", nc->display);
+ query.SetValue("nick", nc->display);
this->RunQuery(query);
}
void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
{
query = "CALL " + prefix + "chanstats_proc_chgdisplay(@old_display@, @new_display@);";
- query.setValue("old_display", nc->display);
- query.setValue("new_display", newdisplay);
+ query.SetValue("old_display", nc->display);
+ query.SetValue("new_display", newdisplay);
this->RunQuery(query);
}
void OnChanDrop(ChannelInfo *ci) anope_override
{
query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
- query.setValue("channel", ci->name);
+ query.SetValue("channel", ci->name);
this->RunQuery(query);
}
};
diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp
index 47f6f41de..a8433fd38 100644
--- a/modules/extra/m_mysql.cpp
+++ b/modules/extra/m_mysql.cpp
@@ -5,6 +5,8 @@
#include <mysql/mysql.h>
#include "sql.h"
+using namespace SQL;
+
/** Non blocking threaded MySQL API, based loosely from InspIRCd's m_mysql.cpp
*
* This module spawns a single thread that is used to execute blocking MySQL queries.
@@ -24,32 +26,32 @@ struct QueryRequest
/* The connection to the database */
MySQLService *service;
/* The interface to use once we have the result to send the data back */
- SQLInterface *sqlinterface;
+ Interface *sqlinterface;
/* The actual query */
- SQLQuery query;
+ Query query;
- QueryRequest(MySQLService *s, SQLInterface *i, const SQLQuery &q) : service(s), sqlinterface(i), query(q) { }
+ QueryRequest(MySQLService *s, Interface *i, const Query &q) : service(s), sqlinterface(i), query(q) { }
};
/** A query result */
struct QueryResult
{
/* The interface to send the data back on */
- SQLInterface *sqlinterface;
+ Interface *sqlinterface;
/* The result */
- SQLResult result;
+ Result result;
- QueryResult(SQLInterface *i, SQLResult &r) : sqlinterface(i), result(r) { }
+ QueryResult(Interface *i, Result &r) : sqlinterface(i), result(r) { }
};
/** A MySQL result
*/
-class MySQLResult : public SQLResult
+class MySQLResult : public Result
{
MYSQL_RES *res;
public:
- MySQLResult(unsigned int i, const SQLQuery &q, const Anope::string &fq, MYSQL_RES *r) : SQLResult(i, q, fq), res(r)
+ MySQLResult(unsigned int i, const Query &q, const Anope::string &fq, MYSQL_RES *r) : Result(i, q, fq), res(r)
{
unsigned num_fields = res ? mysql_num_fields(res) : 0;
@@ -79,7 +81,7 @@ class MySQLResult : public SQLResult
}
}
- MySQLResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(0, q, fq, err), res(NULL)
+ MySQLResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err), res(NULL)
{
}
@@ -92,7 +94,7 @@ class MySQLResult : public SQLResult
/** A MySQL connection, there can be multiple
*/
-class MySQLService : public SQLProvider
+class MySQLService : public Provider
{
std::map<Anope::string, std::set<Anope::string> > active_schema;
@@ -120,21 +122,21 @@ class MySQLService : public SQLProvider
~MySQLService();
- void Run(SQLInterface *i, const SQLQuery &query) anope_override;
+ void Run(Interface *i, const Query &query) anope_override;
- SQLResult RunQuery(const SQLQuery &query) anope_override;
+ Result RunQuery(const Query &query) anope_override;
- std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) anope_override;
+ std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
- SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data);
+ Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) anope_override;
- SQLQuery GetTables(const Anope::string &prefix) anope_override;
+ Query GetTables(const Anope::string &prefix) anope_override;
void Connect();
bool CheckConnection();
- Anope::string BuildQuery(const SQLQuery &q);
+ Anope::string BuildQuery(const Query &q);
Anope::string FromUnixtime(time_t);
};
@@ -235,7 +237,7 @@ class ModuleSQL : public Module, public Pipe
Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << server << ")";
}
- catch (const SQLException &ex)
+ catch (const SQL::Exception &ex)
{
Log(LOG_NORMAL, "mysql") << "MySQL: " << ex.GetReason();
}
@@ -280,7 +282,7 @@ class ModuleSQL : public Module, public Pipe
const QueryResult &qr = *it;
if (!qr.sqlinterface)
- throw SQLException("NULL qr.sqlinterface in MySQLPipe::OnNotify() ?");
+ throw SQL::Exception("NULL qr.sqlinterface in MySQLPipe::OnNotify() ?");
if (qr.result.GetError().empty())
qr.sqlinterface->OnResult(qr.result);
@@ -291,7 +293,7 @@ class ModuleSQL : public Module, public Pipe
};
MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, int po)
-: SQLProvider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
+: Provider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
{
Connect();
}
@@ -310,7 +312,7 @@ MySQLService::~MySQLService()
if (r.service == this)
{
if (r.sqlinterface)
- r.sqlinterface->OnError(SQLResult(0, r.query, "SQL Interface is going away"));
+ r.sqlinterface->OnError(Result(0, r.query, "SQL Interface is going away"));
me->QueryRequests.erase(me->QueryRequests.begin() + i - 1);
}
}
@@ -318,7 +320,7 @@ MySQLService::~MySQLService()
me->DThread->Unlock();
}
-void MySQLService::Run(SQLInterface *i, const SQLQuery &query)
+void MySQLService::Run(Interface *i, const Query &query)
{
me->DThread->Lock();
me->QueryRequests.push_back(QueryRequest(this, i, query));
@@ -326,7 +328,7 @@ void MySQLService::Run(SQLInterface *i, const SQLQuery &query)
me->DThread->Wakeup();
}
-SQLResult MySQLService::RunQuery(const SQLQuery &query)
+Result MySQLService::RunQuery(const Query &query)
{
this->Lock.Lock();
@@ -348,16 +350,16 @@ SQLResult MySQLService::RunQuery(const SQLQuery &query)
}
}
-std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, const Serialize::Data &data)
+std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const Data &data)
{
- std::vector<SQLQuery> queries;
+ std::vector<Query> queries;
std::set<Anope::string> &known_cols = this->active_schema[table];
if (known_cols.empty())
{
Log(LOG_DEBUG) << "m_mysql: Fetching columns for " << table;
- SQLResult columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
+ Result columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
for (int i = 0; i < columns.Rows(); ++i)
{
const Anope::string &column = columns.Get(i, "Field");
@@ -371,15 +373,13 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
{
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
" `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
{
known_cols.insert(it->first);
query_text += ", `" + it->first + "` ";
- if (it->second.GetType() == Serialize::DT_INT)
+ if (data.GetType(it->first) == Serialize::Data::DT_INT)
query_text += "int(11)";
- else if (it->second.GetMax() > 0)
- query_text += "varchar(" + stringify(it->second.GetMax()) + ")";
else
query_text += "text";
}
@@ -387,7 +387,7 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
queries.push_back(query_text);
}
else
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
{
if (known_cols.count(it->first) > 0)
continue;
@@ -395,10 +395,8 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
known_cols.insert(it->first);
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
- if (it->second.GetType() == Serialize::DT_INT)
+ if (data.GetType(it->first) == Serialize::Data::DT_INT)
query_text += "int(11)";
- else if (it->second.GetMax() > 0)
- query_text += "varchar(" + stringify(it->second.GetMax()) + ")";
else
query_text += "text";
@@ -408,35 +406,39 @@ std::vector<SQLQuery> MySQLService::CreateTable(const Anope::string &table, cons
return queries;
}
-SQLQuery MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data)
+Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Data &data) anope_override
{
/* Empty columns not present in the data set */
const std::set<Anope::string> &known_cols = this->active_schema[table];
for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
- if (*it != "id" && *it != "timestamp" && data.count(*it) == 0)
+ if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
data[*it] << "";
Anope::string query_text = "INSERT INTO `" + table + "` (`id`";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
query_text += ",`" + it->first + "`";
query_text += ") VALUES (" + stringify(id);
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
query_text += ",@" + it->first + "@";
query_text += ") ON DUPLICATE KEY UPDATE ";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
query_text += "`" + it->first + "`=VALUES(`" + it->first + "`),";
query_text.erase(query_text.end() - 1);
- SQLQuery query(query_text);
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
- query.setValue(it->first, it->second.astr());
+ Query query(query_text);
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ {
+ Anope::string buf;
+ *it->second >> buf;
+ query.SetValue(it->first, buf);
+ }
return query;
}
-SQLQuery MySQLService::GetTables(const Anope::string &prefix)
+Query MySQLService::GetTables(const Anope::string &prefix)
{
- return SQLQuery("SHOW TABLES LIKE '" + prefix + "%';");
+ return Query("SHOW TABLES LIKE '" + prefix + "%';");
}
void MySQLService::Connect()
@@ -449,7 +451,7 @@ void MySQLService::Connect()
bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, CLIENT_MULTI_RESULTS);
if (!connect)
- throw SQLException("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
+ throw SQL::Exception("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
}
@@ -463,7 +465,7 @@ bool MySQLService::CheckConnection()
{
this->Connect();
}
- catch (const SQLException &)
+ catch (const SQL::Exception &)
{
return false;
}
@@ -479,7 +481,7 @@ Anope::string MySQLService::Escape(const Anope::string &query)
return buffer;
}
-Anope::string MySQLService::BuildQuery(const SQLQuery &q)
+Anope::string MySQLService::BuildQuery(const Query &q)
{
Anope::string real_query = q.query;
@@ -505,7 +507,7 @@ void DispatcherThread::Run()
QueryRequest &r = me->QueryRequests.front();
this->Unlock();
- SQLResult sresult = r.service->RunQuery(r.query);
+ Result sresult = r.service->RunQuery(r.query);
this->Lock();
if (!me->QueryRequests.empty() && me->QueryRequests.front().query == r.query)
diff --git a/modules/extra/m_sql_authentication.cpp b/modules/extra/m_sql_authentication.cpp
index ce7a275b3..e1afbc923 100644
--- a/modules/extra/m_sql_authentication.cpp
+++ b/modules/extra/m_sql_authentication.cpp
@@ -3,13 +3,13 @@
static Module *me;
-class SQLAuthenticationResult : public SQLInterface
+class SQLAuthenticationResult : public SQL::Interface
{
Reference<User> user;
IdentifyRequest *req;
public:
- SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQLInterface(me), user(u), req(r)
+ SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQL::Interface(me), user(u), req(r)
{
req->Hold(me);
}
@@ -19,7 +19,7 @@ class SQLAuthenticationResult : public SQLInterface
req->Release(me);
}
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const SQL::Result &r) anope_override
{
if (r.Rows() == 0)
{
@@ -35,7 +35,7 @@ class SQLAuthenticationResult : public SQLInterface
{
email = r.Get(0, "email");
}
- catch (const SQLException &) { }
+ catch (const SQL::Exception &) { }
NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
@@ -62,7 +62,7 @@ class SQLAuthenticationResult : public SQLInterface
delete this;
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const SQL::Result &r) anope_override
{
Log(this->owner) << "m_sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
delete this;
@@ -76,7 +76,7 @@ class ModuleSQLAuthentication : public Module
bool disable_register;
Anope::string disable_reason;
- ServiceReference<SQLProvider> SQL;
+ ServiceReference<SQL::Provider> SQL;
public:
ModuleSQLAuthentication(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED)
@@ -100,7 +100,7 @@ class ModuleSQLAuthentication : public Module
this->disable_register = config.ReadFlag("m_sql_authentication", "disable_ns_register", "false", 0);
this->disable_reason = config.ReadValue("m_sql_authentication", "disable_reason", "", 0);
- this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
+ this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
}
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
@@ -122,18 +122,18 @@ class ModuleSQLAuthentication : public Module
return;
}
- SQLQuery q(this->query);
- q.setValue("a", req->GetAccount());
- q.setValue("p", req->GetPassword());
+ SQL::Query q(this->query);
+ q.SetValue("a", req->GetAccount());
+ q.SetValue("p", req->GetPassword());
if (u)
{
- q.setValue("n", u->nick);
- q.setValue("i", u->ip);
+ q.SetValue("n", u->nick);
+ q.SetValue("i", u->ip);
}
else
{
- q.setValue("n", "");
- q.setValue("i", "");
+ q.SetValue("n", "");
+ q.SetValue("i", "");
}
diff --git a/modules/extra/m_sql_oper.cpp b/modules/extra/m_sql_oper.cpp
index 523272a49..dd1f13b74 100644
--- a/modules/extra/m_sql_oper.cpp
+++ b/modules/extra/m_sql_oper.cpp
@@ -1,7 +1,7 @@
#include "module.h"
#include "sql.h"
-class SQLOperResult : public SQLInterface
+class SQLOperResult : public SQL::Interface
{
Reference<User> user;
@@ -13,9 +13,9 @@ class SQLOperResult : public SQLInterface
};
public:
- SQLOperResult(Module *m, User *u) : SQLInterface(m), user(u) { }
+ SQLOperResult(Module *m, User *u) : SQL::Interface(m), user(u) { }
- void OnResult(const SQLResult &r) anope_override
+ void OnResult(const SQL::Result &r) anope_override
{
SQLOperResultDeleter d(this);
@@ -27,7 +27,7 @@ class SQLOperResult : public SQLInterface
{
opertype = r.Get(0, "opertype");
}
- catch (const SQLException &)
+ catch (const SQL::Exception &)
{
return;
}
@@ -39,7 +39,7 @@ class SQLOperResult : public SQLInterface
{
modes = r.Get(0, "modes");
}
- catch (const SQLException &) { }
+ catch (const SQL::Exception &) { }
if (opertype.empty())
{
@@ -79,7 +79,7 @@ class SQLOperResult : public SQLInterface
}
}
- void OnError(const SQLResult &r) anope_override
+ void OnError(const SQL::Result &r) anope_override
{
SQLOperResultDeleter d(this);
Log(this->owner) << "m_sql_oper: Error executing query " << r.GetQuery().query << ": " << r.GetError();
@@ -91,7 +91,7 @@ class ModuleSQLOper : public Module
Anope::string engine;
Anope::string query;
- ServiceReference<SQLProvider> SQL;
+ ServiceReference<SQL::Provider> SQL;
public:
ModuleSQLOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED)
@@ -111,7 +111,7 @@ class ModuleSQLOper : public Module
this->engine = config.ReadValue("m_sql_oper", "engine", "", 0);
this->query = config.ReadValue("m_sql_oper", "query", "", 0);
- this->SQL = ServiceReference<SQLProvider>("SQLProvider", this->engine);
+ this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
}
void OnNickIdentify(User *u) anope_override
@@ -122,9 +122,9 @@ class ModuleSQLOper : public Module
return;
}
- SQLQuery q(this->query);
- q.setValue("a", u->Account()->display);
- q.setValue("i", u->ip);
+ SQL::Query q(this->query);
+ q.SetValue("a", u->Account()->display);
+ q.SetValue("i", u->ip);
this->SQL->Run(new SQLOperResult(this, u), q);
diff --git a/modules/extra/m_sqlite.cpp b/modules/extra/m_sqlite.cpp
index 971345475..5d59c3eb9 100644
--- a/modules/extra/m_sqlite.cpp
+++ b/modules/extra/m_sqlite.cpp
@@ -4,22 +4,24 @@
#include <sqlite3.h>
#include "sql.h"
+using namespace SQL;
+
/* SQLite3 API, based from InspiRCd */
/** A SQLite result
*/
-class SQLiteResult : public SQLResult
+class SQLiteResult : public Result
{
public:
- SQLiteResult(unsigned int i, const SQLQuery &q, const Anope::string &fq) : SQLResult(i, q, fq)
+ SQLiteResult(unsigned int i, const Query &q, const Anope::string &fq) : Result(i, q, fq)
{
}
- SQLiteResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(0, q, fq, err)
+ SQLiteResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err)
{
}
- void addRow(const std::map<Anope::string, Anope::string> &data)
+ void AddRow(const std::map<Anope::string, Anope::string> &data)
{
this->entries.push_back(data);
}
@@ -27,7 +29,7 @@ class SQLiteResult : public SQLResult
/** A SQLite database, there can be multiple
*/
-class SQLiteService : public SQLProvider
+class SQLiteService : public Provider
{
std::map<Anope::string, std::set<Anope::string> > active_schema;
@@ -42,17 +44,17 @@ class SQLiteService : public SQLProvider
~SQLiteService();
- void Run(SQLInterface *i, const SQLQuery &query) anope_override;
+ void Run(Interface *i, const Query &query) anope_override;
- SQLResult RunQuery(const SQLQuery &query);
+ Result RunQuery(const Query &query);
- std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) anope_override;
+ std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
- SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data);
+ Query BuildInsert(const Anope::string &table, unsigned int id, Data &data);
- SQLQuery GetTables(const Anope::string &prefix);
+ Query GetTables(const Anope::string &prefix);
- Anope::string BuildQuery(const SQLQuery &q);
+ Anope::string BuildQuery(const Query &q);
Anope::string FromUnixtime(time_t);
};
@@ -116,7 +118,7 @@ class ModuleSQLite : public Module
Log(LOG_NORMAL, "sqlite") << "SQLite: Successfully added database " << database;
}
- catch (const SQLException &ex)
+ catch (const SQL::Exception &ex)
{
Log(LOG_NORMAL, "sqlite") << "SQLite: " << ex.GetReason();
}
@@ -126,11 +128,11 @@ class ModuleSQLite : public Module
};
SQLiteService::SQLiteService(Module *o, const Anope::string &n, const Anope::string &d)
-: SQLProvider(o, n), database(d), sql(NULL)
+: Provider(o, n), database(d), sql(NULL)
{
int db = sqlite3_open_v2(database.c_str(), &this->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
if (db != SQLITE_OK)
- throw SQLException("Unable to open SQLite database " + database + ": " + sqlite3_errmsg(this->sql));
+ throw SQL::Exception("Unable to open SQLite database " + database + ": " + sqlite3_errmsg(this->sql));
}
SQLiteService::~SQLiteService()
@@ -139,16 +141,16 @@ SQLiteService::~SQLiteService()
sqlite3_close(this->sql);
}
-void SQLiteService::Run(SQLInterface *i, const SQLQuery &query)
+void SQLiteService::Run(Interface *i, const Query &query)
{
- SQLResult res = this->RunQuery(query);
+ Result res = this->RunQuery(query);
if (!res.GetError().empty())
i->OnError(res);
else
i->OnResult(res);
}
-SQLResult SQLiteService::RunQuery(const SQLQuery &query)
+Result SQLiteService::RunQuery(const Query &query)
{
Anope::string real_query = this->BuildQuery(query);
sqlite3_stmt *stmt;
@@ -173,7 +175,7 @@ SQLResult SQLiteService::RunQuery(const SQLQuery &query)
if (data && *data)
items[columns[i]] = data;
}
- result.addRow(items);
+ result.AddRow(items);
}
result.id = sqlite3_last_insert_rowid(this->sql);
@@ -186,16 +188,16 @@ SQLResult SQLiteService::RunQuery(const SQLQuery &query)
return result;
}
-std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, const Serialize::Data &data)
+std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const Data &data)
{
- std::vector<SQLQuery> queries;
+ std::vector<Query> queries;
std::set<Anope::string> &known_cols = this->active_schema[table];
if (known_cols.empty())
{
Log(LOG_DEBUG) << "m_sqlite: Fetching columns for " << table;
- SQLResult columns = this->RunQuery("PRAGMA table_info(" + table + ")");
+ Result columns = this->RunQuery("PRAGMA table_info(" + table + ")");
for (int i = 0; i < columns.Rows(); ++i)
{
const Anope::string &column = columns.Get(i, "name");
@@ -209,12 +211,12 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
{
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` INTEGER PRIMARY KEY, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
{
known_cols.insert(it->first);
query_text += ", `" + it->first + "` ";
- if (it->second.GetType() == Serialize::DT_INT)
+ if (data.GetType(it->first) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
@@ -234,7 +236,7 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
queries.push_back(query_text);
}
else
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
{
if (known_cols.count(it->first) > 0)
continue;
@@ -242,7 +244,7 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
known_cols.insert(it->first);
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
- if (it->second.GetType() == Serialize::DT_INT)
+ if (data.GetType(it->first) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
@@ -253,38 +255,42 @@ std::vector<SQLQuery> SQLiteService::CreateTable(const Anope::string &table, con
return queries;
}
-SQLQuery SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data)
+Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Data &data)
{
/* Empty columns not present in the data set */
const std::set<Anope::string> &known_cols = this->active_schema[table];
for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
- if (*it != "id" && *it != "timestamp" && data.count(*it) == 0)
+ if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
data[*it] << "";
Anope::string query_text = "REPLACE INTO `" + table + "` (";
if (id > 0)
query_text += "`id`,";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
query_text += "`" + it->first + "`,";
query_text.erase(query_text.length() - 1);
query_text += ") VALUES (";
if (id > 0)
query_text += stringify(id) + ",";
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
query_text += "@" + it->first + "@,";
query_text.erase(query_text.length() - 1);
query_text += ")";
- SQLQuery query(query_text);
- for (Serialize::Data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
- query.setValue(it->first, it->second.astr());
+ Query query(query_text);
+ for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ {
+ Anope::string buf;
+ *it->second >> buf;
+ query.SetValue(it->first, buf);
+ }
return query;
}
-SQLQuery SQLiteService::GetTables(const Anope::string &prefix)
+Query SQLiteService::GetTables(const Anope::string &prefix)
{
- return SQLQuery("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + prefix + "%';");
+ return Query("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + prefix + "%';");
}
Anope::string SQLiteService::Escape(const Anope::string &query)
@@ -295,7 +301,7 @@ Anope::string SQLiteService::Escape(const Anope::string &query)
return buffer;
}
-Anope::string SQLiteService::BuildQuery(const SQLQuery &q)
+Anope::string SQLiteService::BuildQuery(const Query &q)
{
Anope::string real_query = q.query;
diff --git a/modules/extra/sql.h b/modules/extra/sql.h
index 89686bfe8..f8c7a5961 100644
--- a/modules/extra/sql.h
+++ b/modules/extra/sql.h
@@ -1,139 +1,219 @@
-
-/** A SQL exception, can be thrown at various points
+/*
+ * (C) 2003-2012 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
*/
-class SQLException : public ModuleException
+
+namespace SQL
{
- public:
- SQLException(const Anope::string &reason) : ModuleException(reason) { }
- virtual ~SQLException() throw() { }
-};
+ class Data : public Serialize::Data
+ {
+ public:
+ typedef std::map<Anope::string, std::stringstream *> Map;
+ Map data;
+ std::map<Anope::string, Type> types;
-/** A SQL query
- */
+ ~Data()
+ {
+ Clear();
+ }
-struct QueryData
-{
- Anope::string data;
- bool escape;
-};
+ std::iostream& operator[](const Anope::string &key) anope_override
+ {
+ std::stringstream *&ss = data[key];
+ if (!ss)
+ ss = new std::stringstream();
+ return *ss;
+ }
-struct SQLQuery
-{
- Anope::string query;
- std::map<Anope::string, QueryData> parameters;
+ bool IsEqual(Serialize::Data *other) anope_override
+ {
+ try
+ {
+ Data *o = anope_dynamic_static_cast<Data *>(other);
+
+ for (std::map<Anope::string, std::stringstream *>::const_iterator it = o->data.begin(), it_end = o->data.end(); it != it_end; ++it)
+ if (!this->data.count(it->first) || it->second->str() != this->data[it->first]->str())
+ return false;
+
+ return true;
+ }
+ catch (const CoreException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
+
+ return false;
+ }
- SQLQuery() { }
- SQLQuery(const Anope::string &q) : query(q) { }
+ std::map<Anope::string, std::iostream *> GetData() const
+ {
+ std::map<Anope::string, std::iostream *> d;
+ for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
+ d[it->first] = it->second;
+ return d;
+ }
- SQLQuery& operator=(const Anope::string &q)
- {
- this->query = q;
- this->parameters.clear();
- return *this;
- }
+ void Clear()
+ {
+ for (std::map<Anope::string, std::stringstream *>::iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
+ delete it->second;
+ this->data.clear();
+ }
+
+ void SetType(const Anope::string &key, Type t) anope_override
+ {
+ this->types[key] = t;
+ }
+
+ Type GetType(const Anope::string &key) const anope_override
+ {
+ std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
+ if (it != this->types.end())
+ return it->second;
+ return DT_TEXT;
+ }
+ };
- bool operator==(const SQLQuery &other) const
+ /** A SQL exception, can be thrown at various points
+ */
+ class Exception : public ModuleException
{
- return this->query == other.query;
- }
+ public:
+ Exception(const Anope::string &reason) : ModuleException(reason) { }
+
+ virtual ~Exception() throw() { }
+ };
+
+ /** A SQL query
+ */
- inline bool operator!=(const SQLQuery &other) const
+ struct QueryData
{
- return !(*this == other);
- }
+ Anope::string data;
+ bool escape;
+ };
- template<typename T> void setValue(const Anope::string &key, const T& value, bool escape = true)
+ struct Query
{
- try
+ Anope::string query;
+ std::map<Anope::string, QueryData> parameters;
+
+ Query() { }
+ Query(const Anope::string &q) : query(q) { }
+
+ Query& operator=(const Anope::string &q)
{
- Anope::string string_value = stringify(value);
- this->parameters[key].data = string_value;
- this->parameters[key].escape = escape;
+ this->query = q;
+ this->parameters.clear();
+ return *this;
}
- catch (const ConvertException &ex) { }
- }
-};
-/** A result from a SQL query
- */
-class SQLResult
-{
- protected:
- /* Rows, column, item */
- std::vector<std::map<Anope::string, Anope::string> > entries;
- SQLQuery query;
- Anope::string error;
- public:
- unsigned int id;
- Anope::string finished_query;
+ bool operator==(const Query &other) const
+ {
+ return this->query == other.query;
+ }
- SQLResult() : id(0) { }
- SQLResult(unsigned int i, const SQLQuery &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
+ inline bool operator!=(const Query &other) const
+ {
+ return !(*this == other);
+ }
+
+ template<typename T> void SetValue(const Anope::string &key, const T& value, bool escape = true)
+ {
+ try
+ {
+ Anope::string string_value = stringify(value);
+ this->parameters[key].data = string_value;
+ this->parameters[key].escape = escape;
+ }
+ catch (const ConvertException &ex) { }
+ }
+ };
- inline operator bool() const { return this->error.empty(); }
+ /** A result from a SQL query
+ */
+ class Result
+ {
+ protected:
+ /* Rows, column, item */
+ std::vector<std::map<Anope::string, Anope::string> > entries;
+ Query query;
+ Anope::string error;
+ public:
+ unsigned int id;
+ Anope::string finished_query;
- inline const unsigned int GetID() const { return this->id; }
- inline const SQLQuery &GetQuery() const { return this->query; }
- inline const Anope::string &GetError() const { return this->error; }
+ Result() : id(0) { }
+ Result(unsigned int i, const Query &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
- int Rows() const { return this->entries.size(); }
+ inline operator bool() const { return this->error.empty(); }
- const std::map<Anope::string, Anope::string> &Row(size_t index) const
- {
- try
+ inline const unsigned int GetID() const { return this->id; }
+ inline const Query &GetQuery() const { return this->query; }
+ inline const Anope::string &GetError() const { return this->error; }
+
+ int Rows() const { return this->entries.size(); }
+
+ const std::map<Anope::string, Anope::string> &Row(size_t index) const
{
- return this->entries.at(index);
+ try
+ {
+ return this->entries.at(index);
+ }
+ catch (const std::out_of_range &)
+ {
+ throw Exception("Out of bounds access to SQLResult");
+ }
}
- catch (const std::out_of_range &)
+
+ const Anope::string Get(size_t index, const Anope::string &col) const
{
- throw SQLException("Out of bounds access to SQLResult");
- }
- }
+ const std::map<Anope::string, Anope::string> rows = this->Row(index);
- const Anope::string Get(size_t index, const Anope::string &col) const
- {
- const std::map<Anope::string, Anope::string> rows = this->Row(index);
+ std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
+ if (it == rows.end())
+ throw Exception("Unknown column name in SQLResult: " + col);
- std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
- if (it == rows.end())
- throw SQLException("Unknown column name in SQLResult: " + col);
+ return it->second;
+ }
+ };
- return it->second;
- }
-};
+ /* An interface used by modules to retrieve the results
+ */
+ class Interface
+ {
+ public:
+ Module *owner;
-/* An interface used by modules to retrieve the results
- */
-class SQLInterface
-{
- public:
- Module *owner;
+ Interface(Module *m) : owner(m) { }
+ virtual ~Interface() { }
- SQLInterface(Module *m) : owner(m) { }
- virtual ~SQLInterface() { }
+ virtual void OnResult(const Result &r) = 0;
+ virtual void OnError(const Result &r) = 0;
+ };
- virtual void OnResult(const SQLResult &r) = 0;
- virtual void OnError(const SQLResult &r) = 0;
-};
+ /** Class providing the SQL service, modules call this to execute queries
+ */
+ class Provider : public Service
+ {
+ public:
+ Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { }
-/** Class providing the SQL service, modules call this to execute queries
- */
-class SQLProvider : public Service
-{
- public:
- SQLProvider(Module *c, const Anope::string &n) : Service(c, "SQLProvider", n) { }
+ virtual void Run(Interface *i, const Query &query) = 0;
- virtual void Run(SQLInterface *i, const SQLQuery &query) = 0;
+ virtual Result RunQuery(const Query &query) = 0;
- virtual SQLResult RunQuery(const SQLQuery &query) = 0;
+ virtual std::vector<Query> CreateTable(const Anope::string &table, const Data &data) = 0;
- virtual std::vector<SQLQuery> CreateTable(const Anope::string &table, const Serialize::Data &data) = 0;
+ virtual Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) = 0;
- virtual SQLQuery BuildInsert(const Anope::string &table, unsigned int id, Serialize::Data &data) = 0;
+ virtual Query GetTables(const Anope::string &prefix) = 0;
- virtual SQLQuery GetTables(const Anope::string &prefix) = 0;
+ virtual Anope::string FromUnixtime(time_t) = 0;
+ };
- virtual Anope::string FromUnixtime(time_t) = 0;
-};
+}
diff --git a/modules/extra/webcpanel/pages/chanserv/access.cpp b/modules/extra/webcpanel/pages/chanserv/access.cpp
index d21546c3a..96fa3dca5 100644
--- a/modules/extra/webcpanel/pages/chanserv/access.cpp
+++ b/modules/extra/webcpanel/pages/chanserv/access.cpp
@@ -100,7 +100,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
if ((!highest || *highest <= *new_acc) && !u_access.founder && !has_priv)
delete new_acc;
- else if (new_acc->Serialize().empty())
+ else if (new_acc->AccessSerialize().empty())
{
replacements["MESSAGES"] = "Invalid access expression for the given type";
delete new_acc;