mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 10:39:02 -04:00
255 lines
6.9 KiB
C++
255 lines
6.9 KiB
C++
/*
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
|
*
|
|
* Copyright (C) 2015 Daniel Vassdal <shutter@canternet.org>
|
|
* Copyright (C) 2013, 2017-2019, 2021-2022, 2024 Sadie Powell <sadie@witchery.services>
|
|
* Copyright (C) 2012 Robby <robby@chatbelgie.be>
|
|
* 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 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 single SQL field. */
|
|
typedef std::optional<std::string> Field;
|
|
|
|
/** 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 the result of an SQL query. */
|
|
class SQL::Result
|
|
: public Cullable
|
|
{
|
|
public:
|
|
/**
|
|
* Return the number of rows in the result.
|
|
*
|
|
* Note that if you have performed 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 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.
|
|
*/
|
|
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 final
|
|
{
|
|
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 Cullable
|
|
{
|
|
protected:
|
|
/** Creates a new SQL query. */
|
|
Query(Module* Creator)
|
|
: creator(Creator)
|
|
{
|
|
}
|
|
|
|
public:
|
|
const ModuleRef creator;
|
|
|
|
/** Called when an SQL error happens.
|
|
* @param error The error that occurred.
|
|
*/
|
|
virtual void OnError(const SQL::Error& error) = 0;
|
|
|
|
/** Called when a SQL result is received.
|
|
* @param result The result of the SQL query.
|
|
*/
|
|
virtual void OnResult(SQL::Result& result) = 0;
|
|
};
|
|
|
|
/**
|
|
* Provider object for SQL servers
|
|
*/
|
|
class SQL::Provider
|
|
: public DataProvider
|
|
{
|
|
private:
|
|
/** The name of the database tag in the config. */
|
|
const std::string dbid;
|
|
|
|
public:
|
|
Provider(Module* Creator, const std::string& Name)
|
|
: DataProvider(Creator, "SQL/" + Name)
|
|
, dbid(Name)
|
|
{
|
|
}
|
|
|
|
/** Retrieves the name of the database tag in the config. */
|
|
const std::string& GetId() const { return dbid; }
|
|
|
|
/** 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.insert({
|
|
{ "address", user->GetAddress() },
|
|
{ "dhost", user->GetDisplayedHost() },
|
|
{ "duser", user->GetDisplayedUser() },
|
|
{ "host", user->GetRealHost() },
|
|
{ "nick", user->nick },
|
|
{ "real", user->GetRealName() },
|
|
{ "server", user->server->GetName() },
|
|
{ "sid", user->server->GetId() },
|
|
{ "user", user->GetRealUser() },
|
|
{ "uuid", user->uuid },
|
|
});
|
|
|
|
// Deprecated keys.
|
|
userinfo.insert({
|
|
{ "ident", userinfo["user"] },
|
|
{ "ip" , userinfo["address"] },
|
|
});
|
|
}
|