2012-04-19 20:58:29 +02:00
|
|
|
/*
|
|
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
2010-03-06 16:58:13 +00:00
|
|
|
*
|
2020-01-11 22:02:47 +00:00
|
|
|
* Copyright (C) 2015 Daniel Vassdal <shutter@canternet.org>
|
|
|
|
* Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
|
|
|
|
* Copyright (C) 2013, 2017-2019 Sadie Powell <sadie@witchery.services>
|
|
|
|
* Copyright (C) 2012 Robby <robby@chatbelgie.be>
|
2012-04-19 20:58:29 +02:00
|
|
|
* Copyright (C) 2010 Daniel De Graaf <danieldg@inspircd.org>
|
2010-03-06 16:58:13 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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.
|
2010-03-06 16:58:13 +00:00
|
|
|
*
|
2012-04-19 20:58:29 +02:00
|
|
|
* 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/>.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
|
|
|
|
2012-04-19 20:58:29 +02:00
|
|
|
|
2013-04-02 20:12:15 +01:00
|
|
|
#pragma once
|
2010-03-06 16:58:13 +00:00
|
|
|
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
namespace SQL
|
|
|
|
{
|
|
|
|
class Error;
|
|
|
|
class Provider;
|
|
|
|
class Query;
|
|
|
|
class Result;
|
|
|
|
|
|
|
|
/** A list of parameter replacement values. */
|
|
|
|
typedef std::vector<std::string> ParamList;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** A map of parameter replacement values. */
|
|
|
|
typedef std::map<std::string, std::string> ParamMap;
|
|
|
|
|
2021-03-30 20:24:41 +01:00
|
|
|
/** A single SQL field. */
|
|
|
|
typedef std::optional<std::string> Field;
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** 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. */
|
2018-02-17 17:12:26 +00:00
|
|
|
SUCCESS,
|
2017-12-22 02:47:54 +00:00
|
|
|
|
|
|
|
/** 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);
|
|
|
|
}
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Represents the result of an SQL query. */
|
2021-03-02 05:39:12 +00:00
|
|
|
class SQL::Result : public Cullable
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Return the number of rows in the result.
|
|
|
|
*
|
2020-04-21 06:34:17 +00:00
|
|
|
* Note that if you have performed an INSERT or UPDATE query or other
|
2010-03-06 16:58:13 +00:00
|
|
|
* 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;
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** 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.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
virtual bool GetRow(Row& result) = 0;
|
2010-03-06 19:23:44 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Retrieves a list of SQL columns in the result.
|
|
|
|
* @param result A reference to the vector to store column names in.
|
2010-03-06 19:23:44 +00:00
|
|
|
*/
|
|
|
|
virtual void GetCols(std::vector<std::string>& result) = 0;
|
2015-03-02 03:06:55 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if there's a column with the specified name in the result
|
|
|
|
*
|
2021-03-31 10:38:54 +01:00
|
|
|
* @param column The column name.
|
|
|
|
* @param index The place to store the column index if it exists.
|
|
|
|
* @returns If the column exists then true; otherwise, false.
|
2015-03-02 03:06:55 +01:00
|
|
|
*/
|
|
|
|
virtual bool HasColumn(const std::string& column, size_t& index) = 0;
|
2010-03-06 16:58:13 +00:00
|
|
|
};
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** SQL::Error holds the error state of a request.
|
2010-03-06 16:58:13 +00:00
|
|
|
* The error string varies from database software to database software
|
|
|
|
* and should be used to display informational error messages to users.
|
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
class SQL::Error
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
2017-12-22 02:47:54 +00:00
|
|
|
private:
|
|
|
|
/** The custom error message if one has been specified. */
|
2018-01-01 23:56:35 +00:00
|
|
|
const std::string message;
|
2017-12-22 02:47:54 +00:00
|
|
|
|
2010-03-06 16:58:13 +00:00
|
|
|
public:
|
2017-12-22 02:47:54 +00:00
|
|
|
/** The code which represents this error. */
|
|
|
|
const ErrorCode code;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Initialize an SQL::Error from an error code.
|
|
|
|
* @param c A code which represents this error.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
Error(ErrorCode c)
|
2018-01-01 23:56:35 +00:00
|
|
|
: code(c)
|
2017-12-22 02:47:54 +00:00
|
|
|
{
|
|
|
|
}
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** 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.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2018-01-01 23:56:35 +00:00
|
|
|
Error(ErrorCode c, const std::string m)
|
2017-12-22 02:47:54 +00:00
|
|
|
: message(m)
|
|
|
|
, code(c)
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Retrieves the error message. */
|
|
|
|
const char* ToString() const
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
2018-01-01 23:56:35 +00:00
|
|
|
if (!message.empty())
|
|
|
|
return message.c_str();
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
switch (code)
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
2017-12-22 02:47:54 +00:00
|
|
|
case BAD_DBID:
|
|
|
|
return "Invalid database identifier";
|
|
|
|
case BAD_CONN:
|
2010-03-06 16:58:13 +00:00
|
|
|
return "Invalid connection";
|
2017-12-22 02:47:54 +00:00
|
|
|
case QSEND_FAIL:
|
2010-03-06 16:58:13 +00:00
|
|
|
return "Sending query failed";
|
2017-12-22 02:47:54 +00:00
|
|
|
case QREPLY_FAIL:
|
2010-03-06 16:58:13 +00:00
|
|
|
return "Getting query result failed";
|
|
|
|
default:
|
|
|
|
return "Unknown error";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Object representing an SQL query. This should be allocated on the heap and
|
2017-12-22 02:47:54 +00:00
|
|
|
* passed to an SQL::Provider, which will free it when the query is complete or
|
2010-03-06 16:58:13 +00:00
|
|
|
* 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).
|
|
|
|
*/
|
2021-03-02 05:39:12 +00:00
|
|
|
class SQL::Query : public Cullable
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
2017-12-22 02:47:54 +00:00
|
|
|
protected:
|
|
|
|
/** Creates a new SQL query. */
|
|
|
|
Query(Module* Creator)
|
|
|
|
: creator(Creator)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-03-06 16:58:13 +00:00
|
|
|
public:
|
2017-12-22 02:47:54 +00:00
|
|
|
const ModuleRef creator;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/* Destroys this Query instance. */
|
2020-11-01 02:22:41 +00:00
|
|
|
virtual ~Query() = default;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Called when an SQL error happens.
|
|
|
|
* @param error The error that occurred.
|
|
|
|
*/
|
2021-03-02 05:39:12 +00:00
|
|
|
virtual void OnError(SQL::Error& error) = 0;
|
2017-12-22 02:47:54 +00:00
|
|
|
|
|
|
|
/** Called when a SQL result is received.
|
|
|
|
* @param result The result of the SQL query.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2021-03-02 05:39:12 +00:00
|
|
|
virtual void OnResult(SQL::Result& result) = 0;
|
2010-03-06 16:58:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provider object for SQL servers
|
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
class SQL::Provider : public DataProvider
|
2010-03-06 16:58:13 +00:00
|
|
|
{
|
2019-11-13 12:58:18 +00:00
|
|
|
private:
|
|
|
|
/** The name of the database tag in the config. */
|
|
|
|
const std::string dbid;
|
|
|
|
|
2010-03-06 16:58:13 +00:00
|
|
|
public:
|
2017-12-22 02:47:54 +00:00
|
|
|
Provider(Module* Creator, const std::string& Name)
|
2019-11-13 12:58:18 +00:00
|
|
|
: DataProvider(Creator, "SQL/" + Name)
|
2017-12-22 02:47:54 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-11-13 12:58:18 +00:00
|
|
|
/** Retrieves the name of the database tag in the config. */
|
|
|
|
const std::string& GetId() const { return dbid; }
|
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Submit an asynchronous SQL query.
|
2010-03-13 16:35:16 +00:00
|
|
|
* @param callback The result reporting point
|
|
|
|
* @param query The hardcoded query string. If you have parameters to substitute, see below.
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
virtual void Submit(Query* callback, const std::string& query) = 0;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Submit an asynchronous SQL query.
|
2010-03-13 16:35:16 +00:00
|
|
|
* @param callback The result reporting point
|
|
|
|
* @param format The simple parameterized query string ('?' parameters)
|
|
|
|
* @param p Parameters to fill in for the '?' entries
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
virtual void Submit(Query* callback, const std::string& format, const SQL::ParamList& p) = 0;
|
2010-03-06 16:58:13 +00:00
|
|
|
|
2017-12-22 02:47:54 +00:00
|
|
|
/** Submit an asynchronous SQL query.
|
2010-03-13 16:35:16 +00:00
|
|
|
* @param callback The result reporting point
|
|
|
|
* @param format The parameterized query string ('$name' parameters)
|
|
|
|
* @param p Parameters to fill in for the '$name' entries
|
2010-03-06 16:58:13 +00:00
|
|
|
*/
|
2017-12-22 02:47:54 +00:00
|
|
|
virtual void Submit(Query* callback, const std::string& format, const ParamMap& p) = 0;
|
2010-03-06 16:58:13 +00:00
|
|
|
};
|
2017-12-22 02:47:54 +00:00
|
|
|
|
|
|
|
inline void SQL::PopulateUserInfo(User* user, ParamMap& userinfo)
|
|
|
|
{
|
|
|
|
userinfo["nick"] = user->nick;
|
|
|
|
userinfo["host"] = user->GetRealHost();
|
|
|
|
userinfo["ip"] = user->GetIPString();
|
2018-07-30 18:50:34 +01:00
|
|
|
userinfo["real"] = user->GetRealName();
|
2017-12-22 02:47:54 +00:00
|
|
|
userinfo["ident"] = user->ident;
|
|
|
|
userinfo["server"] = user->server->GetName();
|
|
|
|
userinfo["uuid"] = user->uuid;
|
|
|
|
}
|