mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-10 11:09:04 -04:00
276 lines
7.2 KiB
C++
276 lines
7.2 KiB
C++
/*
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
|
*
|
|
* 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>
|
|
* 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 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 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 Cullable
|
|
{
|
|
protected:
|
|
/** Creates a new SQL query. */
|
|
Query(Module* Creator)
|
|
: creator(Creator)
|
|
{
|
|
}
|
|
|
|
public:
|
|
const ModuleRef creator;
|
|
|
|
/* Destroys this Query instance. */
|
|
virtual ~Query() = default;
|
|
|
|
/** Called when an SQL error happens.
|
|
* @param error The error that occurred.
|
|
*/
|
|
virtual void OnError(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)
|
|
{
|
|
}
|
|
|
|
/** 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["nick"] = user->nick;
|
|
userinfo["host"] = user->GetRealHost();
|
|
userinfo["ip"] = user->GetIPString();
|
|
userinfo["real"] = user->GetRealName();
|
|
userinfo["ident"] = user->ident;
|
|
userinfo["server"] = user->server->GetName();
|
|
userinfo["uuid"] = user->uuid;
|
|
}
|