summaryrefslogtreecommitdiff
path: root/include/modules/sql.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/modules/sql.h')
-rw-r--r--include/modules/sql.h267
1 files changed, 267 insertions, 0 deletions
diff --git a/include/modules/sql.h b/include/modules/sql.h
new file mode 100644
index 000000000..59955107d
--- /dev/null
+++ b/include/modules/sql.h
@@ -0,0 +1,267 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2017 Peter Powell <petpow@saberuk.com>
+ * 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/>.
+ */
+
+
+#pragma once
+
+
+namespace SQL
+{
+ class Error;
+ class Field;
+ class Provider;
+ class Query;
+ class Result;
+
+ /** A list of parameter replacement values. */
+ typedef std::vector<std::string> ParamList;
+
+ /** A map of parameter replacement values. */
+ typedef std::map<std::string, std::string> ParamMap;
+
+ /** A list of SQL fields from a specific row. */
+ typedef std::vector<Field> Row;
+
+ /** An enumeration of possible error codes. */
+ enum ErrorCode
+ {
+ /** No error has occurred. */
+ SUCCESS,
+
+ /** The database identifier is invalid. */
+ BAD_DBID,
+
+ /** The database connection has failed. */
+ BAD_CONN,
+
+ /** Executing the query failed. */
+ QSEND_FAIL,
+
+ /** Reading the response failed. */
+ QREPLY_FAIL
+ };
+
+ /** Populates a parameter map with information about a user.
+ * @param user The user to collect information from.
+ * @param userinfo The map to populate.
+ */
+ void PopulateUserInfo(User* user, ParamMap& userinfo);
+}
+
+/** Represents a single SQL field. */
+class SQL::Field
+{
+ private:
+ /** Whether this SQL field is NULL. */
+ bool null;
+
+ /** The underlying SQL value. */
+ std::string value;
+
+ public:
+ /** Creates a new NULL SQL field. */
+ Field()
+ : null(true)
+ {
+ }
+
+ /** Creates a new non-NULL SQL field.
+ * @param v The value of the field.
+ */
+ Field(const std::string& v)
+ : null(false)
+ , value(v)
+ {
+ }
+
+ /** Determines whether this SQL entry is NULL. */
+ inline bool IsNull() const { return null; }
+
+ /** Retrieves the underlying value. */
+ inline operator const std::string&() const { return value; }
+};
+
+/** Represents the result of an SQL query. */
+class SQL::Result : 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;
+
+ /** Retrieves the next available row from the database.
+ * @param result A list to store the fields from this row in.
+ * @return True if a row could be retrieved; otherwise, false.
+ */
+ virtual bool GetRow(Row& result) = 0;
+
+ /** Retrieves a list of SQL columns in the result.
+ * @param result A reference to the vector to store column names in.
+ */
+ virtual void GetCols(std::vector<std::string>& result) = 0;
+
+ /**
+ * Check if there's a column with the specified name in the result
+ *
+ * @param the column name
+ * @param on success, this is the column index
+ * @returns true, or false if the column is not found
+ */
+ virtual bool HasColumn(const std::string& column, size_t& index) = 0;
+};
+
+/** SQL::Error 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 SQL::Error
+{
+ private:
+ /** The custom error message if one has been specified. */
+ const std::string message;
+
+ public:
+ /** The code which represents this error. */
+ const ErrorCode code;
+
+ /** Initialize an SQL::Error from an error code.
+ * @param c A code which represents this error.
+ */
+ Error(ErrorCode c)
+ : code(c)
+ {
+ }
+
+ /** Initialize an SQL::Error from an error code and a custom error message.
+ * @param c A code which represents this error.
+ * @param m A custom error message.
+ */
+ Error(ErrorCode c, const std::string m)
+ : message(m)
+ , code(c)
+ {
+ }
+
+ /** Retrieves the error message. */
+ const char* ToString() const
+ {
+ if (!message.empty())
+ return message.c_str();
+
+ switch (code)
+ {
+ case BAD_DBID:
+ return "Invalid database identifier";
+ case BAD_CONN:
+ return "Invalid connection";
+ case QSEND_FAIL:
+ return "Sending query failed";
+ case 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 SQL::Provider, 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 SQL::Query : public classbase
+{
+ protected:
+ /** Creates a new SQL query. */
+ Query(Module* Creator)
+ : creator(Creator)
+ {
+ }
+
+ public:
+ const ModuleRef creator;
+
+ /* Destroys this Query instance. */
+ virtual ~Query()
+ {
+ }
+
+ /** Called when an SQL error happens.
+ * @param error The error that occurred.
+ */
+ virtual void OnError(Error& error) = 0;
+
+ /** Called when a SQL result is received.
+ * @param result The result of the SQL query.
+ */
+ virtual void OnResult(Result& result) = 0;
+};
+
+/**
+ * Provider object for SQL servers
+ */
+class SQL::Provider : public DataProvider
+{
+ public:
+ Provider(Module* Creator, const std::string& Name)
+ : DataProvider(Creator, Name)
+ {
+ }
+
+ /** Submit an asynchronous SQL query.
+ * @param callback The result reporting point
+ * @param query The hardcoded query string. If you have parameters to substitute, see below.
+ */
+ virtual void Submit(Query* callback, const std::string& query) = 0;
+
+ /** Submit an asynchronous SQL query.
+ * @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(Query* callback, const std::string& format, const SQL::ParamList& p) = 0;
+
+ /** Submit an asynchronous SQL query.
+ * @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(Query* callback, const std::string& format, const ParamMap& p) = 0;
+};
+
+inline void SQL::PopulateUserInfo(User* user, ParamMap& userinfo)
+{
+ userinfo["nick"] = user->nick;
+ userinfo["host"] = user->GetRealHost();
+ userinfo["ip"] = user->GetIPString();
+ userinfo["gecos"] = user->fullname;
+ userinfo["ident"] = user->ident;
+ userinfo["server"] = user->server->GetName();
+ userinfo["uuid"] = user->uuid;
+}