]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/sql.h
59955107d632d764074ff0e6196bfac4aea83bb9
[user/henk/code/inspircd.git] / include / modules / sql.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2017 Peter Powell <petpow@saberuk.com>
5  *   Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #pragma once
22
23
24 namespace SQL
25 {
26         class Error;
27         class Field;
28         class Provider;
29         class Query;
30         class Result;
31
32         /** A list of parameter replacement values. */
33         typedef std::vector<std::string> ParamList;
34
35         /** A map of parameter replacement values. */
36         typedef std::map<std::string, std::string> ParamMap;
37
38         /** A list of SQL fields from a specific row. */
39         typedef std::vector<Field> Row;
40
41         /** An enumeration of possible error codes. */
42         enum ErrorCode
43         {
44                 /** No error has occurred. */
45                 SUCCESS,
46
47                 /** The database identifier is invalid. */
48                 BAD_DBID,
49
50                 /** The database connection has failed. */
51                 BAD_CONN,
52
53                 /** Executing the query failed. */
54                 QSEND_FAIL,
55
56                 /** Reading the response failed. */
57                 QREPLY_FAIL
58         };
59
60         /** Populates a parameter map with information about a user.
61          * @param user The user to collect information from.
62          * @param userinfo The map to populate.
63          */
64         void PopulateUserInfo(User* user, ParamMap& userinfo);
65 }
66
67 /** Represents a single SQL field. */
68 class SQL::Field
69 {
70  private:
71         /** Whether this SQL field is NULL. */
72         bool null;
73
74         /** The underlying SQL value. */
75         std::string value;
76
77  public:
78         /** Creates a new NULL SQL field. */
79         Field()
80                 : null(true)
81         {
82         }
83
84         /** Creates a new non-NULL SQL field.
85          * @param v The value of the field.
86          */
87         Field(const std::string& v)
88                 : null(false)
89                 , value(v)
90         {
91         }
92
93         /** Determines whether this SQL entry is NULL. */
94         inline bool IsNull() const { return null; }
95
96         /** Retrieves the underlying value. */
97         inline operator const std::string&() const { return value; }
98 };
99
100 /** Represents the result of an SQL query. */
101 class SQL::Result : public classbase
102 {
103  public:
104         /**
105          * Return the number of rows in the result.
106          *
107          * Note that if you have perfomed an INSERT or UPDATE query or other
108          * query which will not return rows, this will return the number of
109          * affected rows. In this case you SHOULD NEVER access any of the result
110          * set rows, as there aren't any!
111          * @returns Number of rows in the result set.
112          */
113         virtual int Rows() = 0;
114
115         /** Retrieves the next available row from the database.
116          * @param result A list to store the fields from this row in.
117          * @return True if a row could be retrieved; otherwise, false.
118          */
119         virtual bool GetRow(Row& result) = 0;
120
121         /** Retrieves a list of SQL columns in the result.
122          * @param result A reference to the vector to store column names in.
123          */
124         virtual void GetCols(std::vector<std::string>& result) = 0;
125
126         /**
127          * Check if there's a column with the specified name in the result
128          *
129          * @param the column name
130          * @param on success, this is the column index
131          * @returns true, or false if the column is not found
132          */
133         virtual bool HasColumn(const std::string& column, size_t& index) = 0;
134 };
135
136 /** SQL::Error holds the error state of a request.
137  * The error string varies from database software to database software
138  * and should be used to display informational error messages to users.
139  */
140 class SQL::Error
141 {
142  private:
143         /** The custom error message if one has been specified. */
144         const std::string message;
145
146  public:
147         /** The code which represents this error. */
148         const ErrorCode code;
149
150         /** Initialize an SQL::Error from an error code.
151          * @param c A code which represents this error.
152          */
153         Error(ErrorCode c)
154                 : code(c)
155         {
156         }
157
158         /** Initialize an SQL::Error from an error code and a custom error message.
159          * @param c A code which represents this error.
160          * @param m A custom error message.
161          */
162         Error(ErrorCode c, const std::string m)
163                 : message(m)
164                 , code(c)
165         {
166         }
167
168         /** Retrieves the error message. */
169         const char* ToString() const
170         {
171                 if (!message.empty())
172                         return message.c_str();
173
174                 switch (code)
175                 {
176                         case BAD_DBID:
177                                 return "Invalid database identifier";
178                         case BAD_CONN:
179                                 return "Invalid connection";
180                         case QSEND_FAIL:
181                                 return "Sending query failed";
182                         case QREPLY_FAIL:
183                                 return "Getting query result failed";
184                         default:
185                                 return "Unknown error";
186                 }
187         }
188 };
189
190 /**
191  * Object representing an SQL query. This should be allocated on the heap and
192  * passed to an SQL::Provider, which will free it when the query is complete or
193  * when the querying module is unloaded.
194  *
195  * You should store whatever information is needed to have the callbacks work in
196  * this object (UID of user, channel name, etc).
197  */
198 class SQL::Query : public classbase
199 {
200  protected:
201         /** Creates a new SQL query. */
202         Query(Module* Creator)
203                 : creator(Creator)
204         {
205         }
206
207  public:
208         const ModuleRef creator;
209
210         /* Destroys this Query instance. */
211         virtual ~Query()
212         {
213         }
214
215         /** Called when an SQL error happens.
216          * @param error The error that occurred.
217          */
218         virtual void OnError(Error& error) = 0;
219
220         /** Called when a SQL result is received.
221          * @param result The result of the SQL query.
222          */
223         virtual void OnResult(Result& result) = 0;
224 };
225
226 /**
227  * Provider object for SQL servers
228  */
229 class SQL::Provider : public DataProvider
230 {
231  public:
232         Provider(Module* Creator, const std::string& Name)
233                 : DataProvider(Creator, Name)
234         {
235         }
236
237         /** Submit an asynchronous SQL query.
238          * @param callback The result reporting point
239          * @param query The hardcoded query string. If you have parameters to substitute, see below.
240          */
241         virtual void Submit(Query* callback, const std::string& query) = 0;
242
243         /** Submit an asynchronous SQL query.
244          * @param callback The result reporting point
245          * @param format The simple parameterized query string ('?' parameters)
246          * @param p Parameters to fill in for the '?' entries
247          */
248         virtual void Submit(Query* callback, const std::string& format, const SQL::ParamList& p) = 0;
249
250         /** Submit an asynchronous SQL query.
251          * @param callback The result reporting point
252          * @param format The parameterized query string ('$name' parameters)
253          * @param p Parameters to fill in for the '$name' entries
254          */
255         virtual void Submit(Query* callback, const std::string& format, const ParamMap& p) = 0;
256 };
257
258 inline void SQL::PopulateUserInfo(User* user, ParamMap& userinfo)
259 {
260         userinfo["nick"] = user->nick;
261         userinfo["host"] = user->GetRealHost();
262         userinfo["ip"] = user->GetIPString();
263         userinfo["gecos"] = user->fullname;
264         userinfo["ident"] = user->ident;
265         userinfo["server"] = user->server->GetName();
266         userinfo["uuid"] = user->uuid;
267 }