summaryrefslogtreecommitdiff
path: root/src/modules/sql.h
blob: 436cd1da8c5ed06d1340ca49fd698326879f1de0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * InspIRCd -- Internet Relay Chat Daemon
 *
 *   Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org>
 *
 * 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/>.
 */


#ifndef INSPIRCD_SQLAPI_3
#define INSPIRCD_SQLAPI_3

/** Defines the error types which SQLerror may be set to
 */
enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL };

/** A list of format parameters for an SQLquery object.
 */
typedef std::vector<std::string> ParamL;

typedef std::map<std::string, std::string> ParamM;

class SQLEntry
{
 public:
	std::string value;
	bool nul;
	SQLEntry() : nul(true) {}
	SQLEntry(const std::string& v) : value(v), nul(false) {}
	inline operator std::string&() { return value; }
};

typedef std::vector<SQLEntry> SQLEntries;

/**
 * Result of an SQL query. Only valid inside OnResult
 */
class SQLResult : public classbase
{
 public:
	/**
	 * Return the number of rows in the result.
	 *
	 * Note that if you have perfomed an INSERT or UPDATE query or other
	 * query which will not return rows, this will return the number of
	 * affected rows. In this case you SHOULD NEVER access any of the result
	 * set rows, as there aren't any!
	 * @returns Number of rows in the result set.
	 */
	virtual int Rows() = 0;

	/**
	 * Return a single row (result of the query). The internal row counter
	 * is incremented by one.
	 *
	 * @param result Storage for the result data.
	 * @returns true if there was a row, false if no row exists (end of
	 * iteration)
	 */
	virtual bool GetRow(SQLEntries& result) = 0;

	/** Returns column names for the items in this row
	 */
	virtual void GetCols(std::vector<std::string>& result) = 0;
};

/** SQLerror holds the error state of a request.
 * The error string varies from database software to database software
 * and should be used to display informational error messages to users.
 */
class SQLerror
{
 public:
	/** The error id
	 */
	SQLerrorNum id;

	/** The error string
	 */
	std::string str;

	/** Initialize an SQLerror
	 * @param i The error ID to set
	 * @param s The (optional) error string to set
	 */
	SQLerror(SQLerrorNum i, const std::string &s = "")
	: id(i), str(s)
	{
	}

	/** Return the error string for an error
	 */
	const char* Str()
	{
		if(str.length())
			return str.c_str();

		switch(id)
		{
			case SQL_BAD_DBID:
				return "Invalid database ID";
			case SQL_BAD_CONN:
				return "Invalid connection";
			case SQL_QSEND_FAIL:
				return "Sending query failed";
			case SQL_QREPLY_FAIL:
				return "Getting query result failed";
			default:
				return "Unknown error";
		}
	}
};

/**
 * Object representing an SQL query. This should be allocated on the heap and
 * passed to an SQLProvider, which will free it when the query is complete or
 * when the querying module is unloaded.
 *
 * You should store whatever information is needed to have the callbacks work in
 * this object (UID of user, channel name, etc).
 */
class SQLQuery : public classbase
{
 public:
	ModuleRef creator;

	SQLQuery(Module* Creator) : creator(Creator) {}
	virtual ~SQLQuery() {}

	virtual void OnResult(SQLResult& result) = 0;
	/**
	 * Called when the query fails
	 */
	virtual void OnError(SQLerror& error) { }
};

/**
 * Provider object for SQL servers
 */
class SQLProvider : public DataProvider
{
 public:
	SQLProvider(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {}
	/** Submit an asynchronous SQL request
	 * @param callback The result reporting point
	 * @param query The hardcoded query string. If you have parameters to substitute, see below.
	 */
	virtual void submit(SQLQuery* callback, const std::string& query) = 0;

	/** Submit an asynchronous SQL request
	 * @param callback The result reporting point
	 * @param format The simple parameterized query string ('?' parameters)
	 * @param p Parameters to fill in for the '?' entries
	 */
	virtual void submit(SQLQuery* callback, const std::string& format, const ParamL& p) = 0;

	/** Submit an asynchronous SQL request.
	 * @param callback The result reporting point
	 * @param format The parameterized query string ('$name' parameters)
	 * @param p Parameters to fill in for the '$name' entries
	 */
	virtual void submit(SQLQuery* callback, const std::string& format, const ParamM& p) = 0;

	/** Convenience function to prepare a map from a User* */
	void PopulateUserInfo(User* user, ParamM& userinfo)
	{
		userinfo["nick"] = user->nick;
		userinfo["host"] = user->host;
		userinfo["ip"] = user->GetIPString();
		userinfo["gecos"] = user->fullname;
		userinfo["ident"] = user->ident;
		userinfo["server"] = user->server;
		userinfo["uuid"] = user->uuid;
	}
};

#endif