1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/module/Library/MySQL.hpp

2728 lines
104 KiB
C++
Raw Permalink Normal View History

2021-06-12 16:51:33 +02:00
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Utility.hpp"
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
#include "Library/Chrono.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Timestamp.hpp"
// ------------------------------------------------------------------------------------------------
#include "Poco/AutoPtr.h"
#include "Poco/Data/SessionImpl.h"
2021-06-12 16:51:33 +02:00
// ------------------------------------------------------------------------------------------------
#include <cstdbool>
#include <unordered_map>
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_POCO_HAS_MYSQL
2021-08-22 18:16:31 +02:00
#include <mysql/mysql.h>
2021-06-12 16:51:33 +02:00
#else
#error Enable MySQL support in order to compile this library.
#endif
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Handle validation.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
#define SQMOD_THROW_CURRENT(x, a) (x).ThrowCurrent(a, __FILE__, __LINE__)
#define SQMOD_VALIDATE(x) (x).Validate(__FILE__, __LINE__)
#define SQMOD_VALIDATE_CREATED(x) (x).ValidateCreated(__FILE__, __LINE__)
#define SQMOD_VALIDATE_PARAM(x, i) (x).ValidateParam((i), __FILE__, __LINE__)
#define SQMOD_VALIDATE_FIELD(x, i) (x).ValidateField((i), __FILE__, __LINE__)
#define SQMOD_VALIDATE_STEPPED(x) (x).ValidateStepped(__FILE__, __LINE__)
#define SQMOD_GET_VALID(x) (x).GetValid(__FILE__, __LINE__)
#define SQMOD_GET_CREATED(x) (x).GetCreated(__FILE__, __LINE__)
#define SQMOD_GET_STEPPED(x) (x).GetStepped(__FILE__, __LINE__)
#else
#define SQMOD_THROW_CURRENT(x, a) (x).ThrowCurrent(a)
#define SQMOD_VALIDATE(x) (x).Validate()
#define SQMOD_VALIDATE_CREATED(x) (x).ValidateCreated()
#define SQMOD_VALIDATE_PARAM(x, i) (x).ValidateParam((i))
#define SQMOD_VALIDATE_FIELD(x, i) (x).ValidateField((i))
#define SQMOD_VALIDATE_STEPPED(x) (x).ValidateStepped()
#define SQMOD_GET_VALID(x) (x).GetValid()
#define SQMOD_GET_CREATED(x) (x).GetCreated()
#define SQMOD_GET_STEPPED(x) (x).GetStepped()
#endif // _DEBUG
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
struct MySQLConnHnd;
struct MySQLStmtHnd;
struct MySQLResHnd;
2021-06-12 16:51:33 +02:00
// ------------------------------------------------------------------------------------------------
class MySQLAccount;
2021-06-12 16:51:33 +02:00
class Column;
class MySQLConnection;
class MySQLResultSet;
class MySQLStatement;
class MySQLTransaction;
2021-06-12 16:51:33 +02:00
/* ------------------------------------------------------------------------------------------------
* Common typedefs.
*/
typedef SharedPtr< MySQLConnHnd > MySQLConnRef;
typedef SharedPtr< MySQLStmtHnd > MySQLStmtRef;
typedef SharedPtr< MySQLResHnd > MySQLResRef;
2021-06-12 16:51:33 +02:00
/* ------------------------------------------------------------------------------------------------
* Replicate the values of a script Date type to a database time type.
*/
void SqDateToMySQLTime(const Date & value, MYSQL_TIME & t);
/* ------------------------------------------------------------------------------------------------
* Replicate the values of a script Date type to a database time type.
*/
void SqTimeToMySQLTime(const Time & value, MYSQL_TIME & t);
/* ------------------------------------------------------------------------------------------------
* Replicate the values of a script Date type to a database time type.
*/
void SqDatetimeToMySQLTime(const Datetime & value, MYSQL_TIME & t);
/* ------------------------------------------------------------------------------------------------
* Retrieve the lowercase name of a MySQL data-type.
*/
SQMOD_NODISCARD const SQChar * SqMySQLTypename(enum_field_types type);
/* ------------------------------------------------------------------------------------------------
* Retrieve the capitalized name of a MySQL data-type.
*/
SQMOD_NODISCARD const SQChar * SqMySQLTypenameC(enum_field_types type);
/* ------------------------------------------------------------------------------------------------
* Utility used to convert from database types to known types.
*/
template < typename T > struct DbConvTo;
/* ------------------------------------------------------------------------------------------------
* Specialization for signed 8 bit integer.
*/
template < > struct DbConvTo< int8_t >
{
SQMOD_NODISCARD static int8_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("int8_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for unsigned 8 bit integer.
*/
template < > struct DbConvTo< uint8_t >
{
SQMOD_NODISCARD static uint8_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("uint8_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for signed 16 bit integer.
*/
template < > struct DbConvTo< int16_t >
{
SQMOD_NODISCARD static int16_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("int16_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for unsigned 16 bit integer.
*/
template < > struct DbConvTo< uint16_t >
{
SQMOD_NODISCARD static uint16_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("uint16_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for signed 32 bit integer.
*/
template < > struct DbConvTo< int32_t >
{
SQMOD_NODISCARD static int32_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("int32_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for unsigned 32 bit integer.
*/
template < > struct DbConvTo< uint32_t >
{
SQMOD_NODISCARD static uint32_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("uint32_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for signed 64 bit integer.
*/
template < > struct DbConvTo< int64_t >
{
SQMOD_NODISCARD static int64_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("int64_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for unsigned 64 bit integer.
*/
template < > struct DbConvTo< uint64_t >
{
SQMOD_NODISCARD static uint64_t From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("uint64_t"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for 32 floating point.
*/
template < > struct DbConvTo< float >
{
SQMOD_NODISCARD static float From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("float"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for 64 floating point.
*/
template < > struct DbConvTo< double >
{
SQMOD_NODISCARD static double From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("double"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for boolean value.
*/
template < > struct DbConvTo< bool >
{
SQMOD_NODISCARD static bool From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("bool"));
};
/* ------------------------------------------------------------------------------------------------
* Specialization for char value.
*/
template < > struct DbConvTo< char >
{
SQMOD_NODISCARD static char From(const SQChar * value, unsigned long length, enum_field_types type, const SQChar * tn = _SC("char"));
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain connection.
*/
struct MySQLConnHnd
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef MYSQL Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type * Pointer; // Pointer to the managed type.
typedef const Type * ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type & Reference; // Reference to the managed type.
typedef const Type & ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef MYSQL_RES ResType; // Database result type.
public:
// --------------------------------------------------------------------------------------------
Pointer mPtr; // The connection handle resource.
// --------------------------------------------------------------------------------------------
uint32_t mErrNo; // Last received error string.
String mErrStr; // Last received error message.
// --------------------------------------------------------------------------------------------
Poco::AutoPtr< Poco::Data::SessionImpl > mSession; // POCO session when this connection comes from a pool.
2021-06-12 16:51:33 +02:00
// --------------------------------------------------------------------------------------------
uint16_t mPort; // Server port.
String mHost; // Host address.
String mUser; // User name user.
String mPass; // User password.
String mName; // Database name.
String mSocket; // Unix socket.
unsigned long mFlags; // Client flags.
// --------------------------------------------------------------------------------------------
String mSSL_Key; // SSL key.
String mSSL_Cert; // SSL certificate.
String mSSL_CA; // SSL certificate authority.
String mSSL_CA_Path; // SSL certificate authority path.
String mSSL_Cipher; // SSL Cipher.
// --------------------------------------------------------------------------------------------
String mCharset; // Default connection character set.
// --------------------------------------------------------------------------------------------
bool mAutoCommit; // Whether autocommit is enabled on this connection.
bool mInTransaction; // Whether the connection is in the middle of a transaction.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLConnHnd();
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit MySQLConnHnd(Poco::Data::SessionImpl * session);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
explicit MySQLConnHnd(Poco::AutoPtr< Poco::Data::SessionImpl > && session);
/* --------------------------------------------------------------------------------------------
2021-06-12 16:51:33 +02:00
* Destructor.
*/
~MySQLConnHnd();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Grab the current error in the connection handle.
*/
void GrabCurrent();
/* --------------------------------------------------------------------------------------------
* Grab the current error in the connection handle and throw it.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ThrowCurrent(const char * act, const char * file, int32_t line);
#else
void ThrowCurrent(const char * act);
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Create the connection handle.
*/
void Create(const MySQLAccount & acc);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Disconnect the managed connection handle.
*/
void Disconnect();
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
uint64_t Execute(const SQChar * query, unsigned long size = 0UL);
/* --------------------------------------------------------------------------------------------
* Access the connection pointer.
*/
SQMOD_NODISCARD Pointer Access() const
{
if (!mSession.isNull()) {
// Only reason this is necessary is to dirty the connection handle access time-stamp
// So it won't be closed/collected when it comes from a connection/session-pool
[[maybe_unused]] auto _ = mSession->isConnected();
}
// We yield access to the pointer anyway
return mPtr;
}
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain bind point.
*/
struct MySQLStmtBind // NOLINT(cppcoreguidelines-pro-type-member-init)
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef MYSQL_STMT Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type * Pointer; // Pointer to the managed type.
typedef const Type * ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type & Reference; // Reference to the managed type.
typedef const Type & ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef MYSQL_BIND BindType; // Database bind type.
typedef MYSQL_TIME TimeType; // Database time type.
#if (defined(MYSQL_VERSION_ID) && (MYSQL_VERSION_ID < 80000)) || defined(LIBMARIADB)
typedef my_bool BoolType; // Database boolean type.
#else
typedef _Bool BoolType; // Database boolean type.
#endif
public:
// --------------------------------------------------------------------------------------------
BoolType mIsNull{false}; // Allows the database to specify if the parameter is null.
BoolType mError{false}; // Allows the database if errors occurred on this parameter.
Buffer mData{}; // Buffer to store non fundamental data for the parameter.
BindType * mBind{nullptr}; // The associated database bind point handle.
TimeType mTime{0}; // Structure used to store time data from database.
// --------------------------------------------------------------------------------------------
union
{
uint64_t mUint64; // Store unsigned integer values for the parameter.
int64_t mInt64; // Store signed integer values for the parameter.
int32_t mInt32[2]; // Store 32 bit signed integer values for the parameter.
double mFloat64; // Store 32 bit floating point values for the parameter.
float mFloat32[2]; // Store 64 bit floating point values for the parameter.
};
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLStmtBind() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
MySQLStmtBind(const MySQLStmtBind & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
MySQLStmtBind(MySQLStmtBind && o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
MySQLStmtBind & operator = (const MySQLStmtBind & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
MySQLStmtBind & operator = (MySQLStmtBind && o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Retrieve the used buffer.
*/
SQMOD_NODISCARD char * GetBuffer()
{
return mData ? mData.Data() : reinterpret_cast< char * >(&mUint64);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the buffer length.
*/
SQMOD_NODISCARD unsigned long GetLength() const
{
return (mBind == nullptr) ? 0 : mBind->buffer_length;
}
/* --------------------------------------------------------------------------------------------
* Configure the input of a certain statement parameter.
*/
void SetInput(enum_field_types type, BindType * bind, const char * buffer = nullptr, unsigned long length = 0);
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain statement handle.
*/
struct MySQLStmtHnd
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef MYSQL_STMT Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type * Pointer; // Pointer to the managed type.
typedef const Type * ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type & Reference; // Reference to the managed type.
typedef const Type & ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef MYSQL_BIND BindType; // Database bind type.
typedef MYSQL_TIME TimeType; // Database time type.
#if (defined(MYSQL_VERSION_ID) && (MYSQL_VERSION_ID < 80000)) || defined(LIBMARIADB)
typedef my_bool BoolType; // Database boolean type.
#else
typedef _Bool BoolType; // Database boolean type.
#endif
public:
// --------------------------------------------------------------------------------------------
Pointer mPtr; // The managed statement handle.
// --------------------------------------------------------------------------------------------
uint32_t mErrNo; // Last received error string.
String mErrStr; // Last received error message.
// --------------------------------------------------------------------------------------------
unsigned long mParams; // Number of parameters in the statement.
MySQLStmtBind * mBinds; // List of parameter binds.
2021-06-12 16:51:33 +02:00
BindType * mMyBinds; // List of parameter binds.
// --------------------------------------------------------------------------------------------
MySQLConnRef mConnection; // Reference to the associated connection.
2021-06-12 16:51:33 +02:00
String mQuery; // The query string.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLStmtHnd();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLStmtHnd();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Grab the current error in the associated statement handle.
*/
void GrabCurrent();
/* --------------------------------------------------------------------------------------------
* Grab the current error in the associated statement handle and throw it.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ThrowCurrent(const char * act, const char * file, int32_t line);
#else
void ThrowCurrent(const char * act);
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated statement handle and parameter index and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateParam(uint32_t idx, const char * file, int32_t line) const;
#else
void ValidateParam(uint32_t idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Check whether a specific param index is within range.
*/
SQMOD_NODISCARD bool CheckParamIndex(uint32_t idx) const
{
return (idx < mParams);
}
/* --------------------------------------------------------------------------------------------
* Create the actual statement.
*/
void Create(const MySQLConnRef & conn, const SQChar * query);
/* --------------------------------------------------------------------------------------------
* Access the statement pointer.
*/
SQMOD_NODISCARD Pointer Access() const
{
if (bool(mConnection) && !(mConnection->mSession.isNull())) {
// Only reason this is necessary is to dirty the connection handle access time-stamp
// So it won't be closed/collected when it comes from a connection/session-pool
[[maybe_unused]] auto _ = mConnection->mSession->isConnected();
}
// We yield access to the pointer anyway
return mPtr;
}
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain field.
*/
struct MySQLResBind // NOLINT(cppcoreguidelines-pro-type-member-init)
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef MYSQL_RES Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type * Pointer; // Pointer to the managed type.
typedef const Type * ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type & Reference; // Reference to the managed type.
typedef const Type & ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef MYSQL_FIELD FieldType; // Database field type.
typedef MYSQL_BIND BindType; // Database bind type.
typedef MYSQL_TIME TimeType; // Database time type.
typedef MYSQL_ROW RowType; // Database row type.
#if (defined(MYSQL_VERSION_ID) && (MYSQL_VERSION_ID < 80000)) || defined(LIBMARIADB)
typedef my_bool BoolType; // Database boolean type.
#else
typedef _Bool BoolType; // Database boolean type.
#endif
// --------------------------------------------------------------------------------------------
typedef std::unordered_map< String, uint32_t > IndexMap;
public:
// --------------------------------------------------------------------------------------------
BoolType mIsNull{false}; // Allows the database to specify if the field is null.
BoolType mError{false}; // Allows the database if errors occurred on this field.
Buffer mData{}; // Buffer to store non fundamental data for the field.
BindType * mBind{nullptr}; // The associated database bind point handle.
TimeType mTime{0}; // Structure used to retrieve time data from database.
// --------------------------------------------------------------------------------------------
union
{
uint64_t mUint64{}; // Retrieve unsigned integer values from a field.
int64_t mInt64; // Retrieve signed integer values from a field.
int32_t mInt32[2]; // Retrieve 32 bit signed integer values from a field.
double mFloat64; // Retrieve 32 bit floating point values from a field.
float mFloat32[2]; // Retrieve 64 bit floating point values from the field.
};
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLResBind() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
MySQLResBind(const MySQLResBind & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
MySQLResBind(MySQLResBind && o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
MySQLResBind & operator = (const MySQLResBind & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
MySQLResBind & operator = (MySQLResBind && o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Retrieve the used buffer.
*/
SQMOD_NODISCARD char * GetBuffer()
2021-06-12 16:51:33 +02:00
{
return mData ? mData.Data() : reinterpret_cast< char * >(&mUint64);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the buffer length.
*/
SQMOD_NODISCARD unsigned long GetLength() const
{
return mBind == nullptr ? 0 : mBind->buffer_length;
}
/* --------------------------------------------------------------------------------------------
* Configure the output to match the requirements of a certain field.
*/
void SetOutput(const FieldType & field, BindType * bind);
};
/* ------------------------------------------------------------------------------------------------
* The structure that holds the data associated with a certain result-set handle.
*/
struct MySQLResHnd
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef MYSQL_RES Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type * Pointer; // Pointer to the managed type.
typedef const Type * ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type & Reference; // Reference to the managed type.
typedef const Type & ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef MYSQL_FIELD FieldType; // Database field type.
typedef MYSQL_BIND BindType; // Database bind type.
typedef MYSQL_TIME TimeType; // Database time type.
typedef MYSQL_ROW RowType; // Database row type.
#if (defined(MYSQL_VERSION_ID) && (MYSQL_VERSION_ID < 80000)) || defined(LIBMARIADB)
typedef my_bool BoolType; // Database boolean type.
#else
typedef _Bool BoolType; // Database boolean type.
#endif
// --------------------------------------------------------------------------------------------
typedef std::unordered_map< String, uint32_t > IndexMap; // Name to index association of fields.
public:
// --------------------------------------------------------------------------------------------
Pointer mPtr; // The managed result-set handle.
// --------------------------------------------------------------------------------------------
uint32_t mFieldCount; // Number of fields in the result-set.
unsigned long * mLengths; // Data length when the result-set came from a connection.
FieldType * mFields; // Fields in the results set.
MySQLResBind * mBinds; // Bind wrappers.
2021-06-12 16:51:33 +02:00
BindType * mMyBinds; // Bind points.
RowType mRow; // Row data.
// --------------------------------------------------------------------------------------------
MySQLConnRef mConnection; // Associated connection.
MySQLStmtRef mStatement; // Associated statement.
IndexMap mIndexes; // MySQLField names and their associated index.
2021-06-12 16:51:33 +02:00
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLResHnd();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLResHnd();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Grab the current error in the associated statement or connection handle.
*/
void GrabCurrent() const;
/* --------------------------------------------------------------------------------------------
* Grab the current error in the associated statement or connection handle and throw it.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ThrowCurrent(const char * act, const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
void ThrowCurrent(const char * act) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement handle and field index and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateField(uint32_t idx, const char * file, int32_t line) const;
#else
void ValidateField(uint32_t idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Check whether a specific field index is within range.
*/
bool CheckFieldIndex(uint32_t idx) const
{
return (idx < mFieldCount);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the field index associated with the specified name.
*/
uint32_t GetFieldIndex(const SQChar * name);
/* --------------------------------------------------------------------------------------------
* Create the result-set from a MySQLConnection.
2021-06-12 16:51:33 +02:00
*/
void Create(const MySQLConnRef & conn);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Create the result-set from a MySQLStatement.
2021-06-12 16:51:33 +02:00
*/
void Create(const MySQLStmtRef & stmt);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Returns the current position of the row cursor for the last Next().
*/
uint64_t RowIndex() const;
/* --------------------------------------------------------------------------------------------
* Returns the number of rows in the result set.
*/
uint64_t RowCount() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the next row from the query.
*/
bool Next();
/* --------------------------------------------------------------------------------------------
* Seeks to an arbitrary row in a query result set.
*/
bool SetRowIndex(uint64_t index);
/* --------------------------------------------------------------------------------------------
* Access the resource pointer.
*/
SQMOD_NODISCARD Pointer Access() const
{
if (bool(mConnection) && !(mConnection->mSession.isNull())) {
// Only reason this is necessary is to dirty the connection handle access time-stamp
// So it won't be closed/collected when it comes from a connection/session-pool
[[maybe_unused]] auto _ = mConnection->mSession->isConnected();
}
// We yield access to the pointer anyway
return mPtr;
}
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* Helper class containing shared connection information to avoid repetition.
*/
class MySQLAccount
2021-06-12 16:51:33 +02:00
{
public:
// --------------------------------------------------------------------------------------------
typedef std::unordered_map< String, String > Options;
private:
// --------------------------------------------------------------------------------------------
uint16_t m_Port; // Server port.
String m_Host; // Host address.
String m_User; // User name.
String m_Pass; // User password.
String m_Name; // Database name.
String m_Socket; // Unix socket.
unsigned long m_Flags; // Client connection flags.
// --------------------------------------------------------------------------------------------
String m_SSL_Key; // SSL key.
String m_SSL_Cert; // SSL certificate.
String m_SSL_CA; // SSL certificate authority.
String m_SSL_CA_Path; // SSL certificate authority path.
String m_SSL_Cipher; // SSL Cipher.
// --------------------------------------------------------------------------------------------
Options m_Options; // Option container.
// --------------------------------------------------------------------------------------------
bool m_AutoCommit; // Toggle autocommit.
// --------------------------------------------------------------------------------------------
static const String s_String; // Dummy used to return a reference to a null string.
public:
/* --------------------------------------------------------------------------------------------
* Base Constructor.
*/
MySQLAccount(const SQChar * host, const SQChar * user)
: MySQLAccount(host, user, _SC(""), _SC(""), 3306, _SC(""))
2021-06-12 16:51:33 +02:00
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base Constructor.
*/
MySQLAccount(const SQChar * host, const SQChar * user, const SQChar * pass)
: MySQLAccount(host, user, pass, _SC(""), 3306, _SC(""))
2021-06-12 16:51:33 +02:00
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base Constructor.
*/
MySQLAccount(const SQChar * host, const SQChar * user, const SQChar * pass, const SQChar * name)
: MySQLAccount(host, user, pass, name, 3306, _SC(""))
2021-06-12 16:51:33 +02:00
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base Constructor.
*/
MySQLAccount(const SQChar * host, const SQChar * user, const SQChar * pass, const SQChar * name, SQInteger port)
: MySQLAccount(host, user, pass, name, port, _SC(""))
2021-06-12 16:51:33 +02:00
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base Constructor.
*/
MySQLAccount(const SQChar * host, const SQChar * user, const SQChar * pass, const SQChar * name, SQInteger port, const SQChar * socket);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLAccount(const MySQLAccount & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLAccount(MySQLAccount && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLAccount() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLAccount & operator = (const MySQLAccount & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLAccount & operator = (MySQLAccount && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
int32_t Cmp(const MySQLAccount & o) const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
String ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the host address specified during creation.
*/
const String & GetHost() const
{
return m_Host;
}
/* --------------------------------------------------------------------------------------------
* Modify the host address specified during creation.
*/
void SetHost(const SQChar * addr);
/* --------------------------------------------------------------------------------------------
* Retrieve the user name specified during creation.
*/
const String & GetUser() const
{
return m_User;
}
/* --------------------------------------------------------------------------------------------
* Modify the user name specified during creation.
*/
void SetUser(const SQChar * user)
{
m_User.assign(user != nullptr ? user : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the password specified during creation.
*/
const String & GetPass() const
{
return m_Pass;
}
/* --------------------------------------------------------------------------------------------
* Modify the password specified during creation.
*/
void SetPass(const SQChar * pass)
{
m_Pass.assign(pass != nullptr ? pass : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the database name specified during creation.
*/
const String & GetName() const
{
return m_Name;
}
/* --------------------------------------------------------------------------------------------
* Modify the database name specified during creation.
*/
void SetName(const SQChar * name)
{
m_Name.assign(name != nullptr ? name : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the server port specified during creation.
*/
uint16_t GetPortNum() const
{
return m_Port;
}
/* --------------------------------------------------------------------------------------------
* Modify the server port specified during creation.
*/
void SetPortNum(SQInteger port);
/* --------------------------------------------------------------------------------------------
* Retrieve the server socket.
*/
const String & GetSocket() const
{
return m_Socket;
}
/* --------------------------------------------------------------------------------------------
* Modify the server socket.
*/
void SetSocket(const SQChar * socket)
{
m_Socket.assign(socket != nullptr ? socket : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current client connection flags.
*/
SQInteger GetFlags() const
{
return m_Flags;
}
/* --------------------------------------------------------------------------------------------
* Modify the current client connection flags.
*/
void SetFlags(SQInteger flags)
{
m_Flags = static_cast<unsigned long>(flags);
}
/* --------------------------------------------------------------------------------------------
* Modify the current client connection flags.
*/
void EnableFlags(SQInteger flags)
{
m_Flags |= flags;
}
/* --------------------------------------------------------------------------------------------
* Modify the current client connection flags.
*/
void DisableFlags(SQInteger flags)
{
m_Flags |= flags;
m_Flags ^= flags;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the SSL key.
*/
const String & GetSSL_Key() const
{
return m_SSL_Key;
}
/* --------------------------------------------------------------------------------------------
* Modify the SSL key.
*/
void SetSSL_Key(const SQChar * key)
{
m_SSL_Key.assign(key != nullptr ? key : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the SSL certificate.
*/
const String & GetSSL_Cert() const
{
return m_SSL_Cert;
}
/* --------------------------------------------------------------------------------------------
* Modify the SSL certificate.
*/
void SetSSL_Cert(const SQChar * cert)
{
m_SSL_Cert.assign(cert != nullptr ? cert : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the SSL certificate authority.
*/
const String & GetSSL_CA() const
{
return m_SSL_CA;
}
/* --------------------------------------------------------------------------------------------
* Modify the SSL certificate authority.
*/
void SetSSL_CA(const SQChar * ca)
{
m_SSL_CA.assign(ca != nullptr ? ca : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the SSL certificate authority path.
*/
const String & GetSSL_CA_Path() const
{
return m_SSL_CA_Path;
}
/* --------------------------------------------------------------------------------------------
* Modify the SSL certificate authority path.
*/
void SetSSL_CA_Path(const SQChar * capath)
{
m_SSL_CA_Path.assign(capath != nullptr ? capath : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the SSL cipher.
*/
const String & GetSSL_Cipher() const
{
return m_SSL_Cipher;
}
/* --------------------------------------------------------------------------------------------
* Modify the SSL cipher.
*/
void SetSSL_Cipher(const SQChar * cipher)
{
m_SSL_Cipher.assign(cipher != nullptr ? cipher : _SC(""));
}
/* --------------------------------------------------------------------------------------------
* Set the SSL information.
*/
void SetSSL(const SQChar * key, const SQChar * cert, const SQChar * ca, const SQChar * ca_path, const SQChar * cipher);
/* --------------------------------------------------------------------------------------------
* See whether autocommit is enabled or not.
*/
bool GetAutoCommit() const
{
return m_AutoCommit;
}
/* --------------------------------------------------------------------------------------------
* Set whether autocommit should be enabled or not.
*/
void SetAutoCommit(bool toggle)
{
m_AutoCommit = toggle;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the entire options container as a table.
*/
const Options & GetOptions() const
{
return m_Options;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the entire options container as a table.
*/
Table GetOptionsTable() const;
/* --------------------------------------------------------------------------------------------
* Retrieve a value from the options container.
*/
const String & GetOption(const SQChar * name) const;
/* --------------------------------------------------------------------------------------------
* Set a value in the options container.
*/
void SetOption(const SQChar * name, const SQChar * value);
/* --------------------------------------------------------------------------------------------
* Remove a value from the options container.
*/
void RemoveOption(const SQChar * name);
/* --------------------------------------------------------------------------------------------
* Retrieve the number of values in the options container.
*/
uint32_t OptionsCount() const
{
return static_cast< uint32_t >(m_Options.size());
}
/* --------------------------------------------------------------------------------------------
* See whether the options container is empty or not.
*/
bool OptionsEmpty() const
{
return m_Options.empty();
}
/* --------------------------------------------------------------------------------------------
* Remove all the options from the options container.
*/
void OptionsClear()
{
m_Options.clear();
}
/* --------------------------------------------------------------------------------------------
* Create a connection with the current account information.
*/
MySQLConnection Connect() const;
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* Allows management and interaction with a connection handle.
*/
class MySQLConnection
2021-06-12 16:51:33 +02:00
{
private:
// --------------------------------------------------------------------------------------------
MySQLConnRef m_Handle{}; // Reference to the actual database connection.
2021-06-12 16:51:33 +02:00
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(const char * file, int32_t line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(const char * file, int32_t line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const MySQLConnRef & GetValid(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLConnRef & GetValid() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed connection handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const MySQLConnRef & GetCreated(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLConnRef & GetCreated() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLConnection() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
explicit MySQLConnection(const MySQLAccount & acc)
: m_Handle(new MySQLConnHnd())
2021-06-12 16:51:33 +02:00
{
m_Handle->Create(acc);
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
explicit MySQLConnection(const MySQLConnRef & conn) // NOLINT(modernize-pass-by-value)
2021-06-12 16:51:33 +02:00
: m_Handle(conn)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLConnection(const MySQLConnection & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLConnection(MySQLConnection && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLConnection & operator = (const MySQLConnection & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLConnection & operator = (MySQLConnection && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
SQMOD_NODISCARD int32_t Cmp(const MySQLConnection & o) const
2021-06-12 16:51:33 +02:00
{
if (m_Handle.Get() == o.m_Handle.Get())
{
return 0;
}
else if (m_Handle.Get() > o.m_Handle.Get())
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
SQMOD_NODISCARD const SQChar * ToString() const
{
return m_Handle ? mysql_get_host_info(m_Handle->Access()) : _SC("");
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
SQMOD_NODISCARD static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated connection handle.
*/
SQMOD_NODISCARD const MySQLConnRef & GetHandle() const
2021-06-12 16:51:33 +02:00
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed handle is valid.
*/
SQMOD_NODISCARD bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed connection handle was connected.
*/
SQMOD_NODISCARD bool IsConnected() const
{
return m_Handle && (m_Handle->Access() != nullptr);
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this connection handle.
*/
SQMOD_NODISCARD uint32_t GetRefCount() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current error number.
*/
SQMOD_NODISCARD SQInteger GetErrNo() const
{
return static_cast< SQInteger >(mysql_errno(SQMOD_GET_CREATED(*this)->mPtr));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current error message.
*/
SQMOD_NODISCARD const SQChar * GetErrStr() const
{
return mysql_error(SQMOD_GET_CREATED(*this)->mPtr);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the last received error number.
*/
SQMOD_NODISCARD SQInteger GetLastErrNo() const
{
return static_cast< SQInteger >(SQMOD_GET_VALID(*this)->mErrNo);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the last received error message.
*/
SQMOD_NODISCARD const String & GetLastErrStr() const
{
return SQMOD_GET_VALID(*this)->mErrStr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection port number.
*/
SQMOD_NODISCARD SQInteger GetPortNum() const
{
return static_cast< SQInteger >(SQMOD_GET_VALID(*this)->mPort);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection host address.
*/
SQMOD_NODISCARD const String & GetHost() const
{
return SQMOD_GET_VALID(*this)->mHost;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection user name.
*/
SQMOD_NODISCARD const String & GetUser() const
{
return SQMOD_GET_VALID(*this)->mUser;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection password.
*/
SQMOD_NODISCARD const String & GetPass() const
{
return SQMOD_GET_VALID(*this)->mPass;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the selected database name.
*/
SQMOD_NODISCARD const String & GetName() const
{
return SQMOD_GET_VALID(*this)->mName;
}
/* --------------------------------------------------------------------------------------------
* Modify the selected database name.
*/
void SetName(const SQChar * name)
{
// Validate the specified name
if (!name)
{
STHROWF("Invalid MySQL database name");
}
// Attempt to select the database with the given name
else if (mysql_select_db(SQMOD_GET_CREATED(*this)->mPtr, name) != 0)
{
SQMOD_THROW_CURRENT(*m_Handle, "Cannot select MySQL database");
}
// Remember the database name
m_Handle->mName.assign(name);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection socket.
*/
SQMOD_NODISCARD const String & GetSocket() const
{
return SQMOD_GET_VALID(*this)->mSocket;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection flags.
*/
SQMOD_NODISCARD SQInteger GetFlags() const
{
return static_cast< SQInteger >(SQMOD_GET_VALID(*this)->mFlags);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection SSL key.
*/
SQMOD_NODISCARD const String & GetSSL_Key() const
{
return SQMOD_GET_VALID(*this)->mSSL_Key;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection SSL certificate.
*/
SQMOD_NODISCARD const String & GetSSL_Cert() const
{
return SQMOD_GET_VALID(*this)->mSSL_Cert;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection SSL certificate authority.
*/
SQMOD_NODISCARD const String & GetSSL_CA() const
{
return SQMOD_GET_VALID(*this)->mSSL_CA;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection SSL certificate authority path.
*/
SQMOD_NODISCARD const String & GetSSL_CA_Path() const
{
return SQMOD_GET_VALID(*this)->mSSL_CA_Path;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the connection SSL cipher.
*/
SQMOD_NODISCARD const String & GetSSL_Cipher() const
{
return SQMOD_GET_VALID(*this)->mSSL_Cipher;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the default character set for the managed connection.
*/
SQMOD_NODISCARD const String & GetCharset() const
{
return SQMOD_GET_VALID(*this)->mCharset;
}
/* --------------------------------------------------------------------------------------------
* Modify the default character set for the managed connection.
*/
void SetCharset(const SQChar * charset)
{
// Validate the specified string
if (!charset)
{
STHROWF("Invalid charset string");
}
// Attempt to Set the default character set for the managed connection
else if (mysql_set_character_set(SQMOD_GET_CREATED(*this)->mPtr, charset) != 0)
{
SQMOD_THROW_CURRENT(*m_Handle, "Cannot apply character set");
}
// Remember the character set
m_Handle->mCharset.assign(charset);
}
/* --------------------------------------------------------------------------------------------
* See whether auto-commit is enabled or not.
*/
SQMOD_NODISCARD bool GetAutoCommit() const
{
return SQMOD_GET_VALID((*this))->mAutoCommit;
}
/* --------------------------------------------------------------------------------------------
* Set whether auto-commit should be enabled or not.
*/
void SetAutoCommit(bool toggle)
{
// Attempt to toggle auto-commit if necessary
if (SQMOD_GET_CREATED(*this)->mAutoCommit != toggle &&
mysql_autocommit(m_Handle->Access(), static_cast< MySQLStmtBind::BoolType >(toggle)) != 0)
2021-06-12 16:51:33 +02:00
{
SQMOD_THROW_CURRENT(*m_Handle, "Cannot toggle auto-commit");
}
else
{
m_Handle->mAutoCommit = toggle;
}
}
/* --------------------------------------------------------------------------------------------
* See whether the connection is in the middle of a transaction.
*/
SQMOD_NODISCARD bool GetInTransaction() const
{
return SQMOD_GET_VALID(*this)->mInTransaction;
}
/* --------------------------------------------------------------------------------------------
* Disconnect from the currently connected database.
*/
void Disconnect()
{
SQMOD_GET_CREATED(*this)->Disconnect();
}
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
SQInteger Execute(const SQChar * query)
2021-06-12 16:51:33 +02:00
{
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->Execute(query));
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
SQInteger Insert(const SQChar * query);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Execute a query on the server.
*/
MySQLResultSet Query(const SQChar * query);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Create a new statement on the managed connection.
*/
SQMOD_NODISCARD MySQLStatement GetStatement(const SQChar * query);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Create a new transaction on the managed connection.
*/
//SQMOD_NODISCARD MySQLTransaction GetTransaction();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Escape unwanted characters from a given string.
*/
SQMOD_NODISCARD LightObj EscapeString(StackStrF & str);
/* --------------------------------------------------------------------------------------------
* Attempt to execute the specified query.
*/
static SQInteger ExecuteF(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Attempt to execute the specified query.
*/
static SQInteger InsertF(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Attempt to execute the specified query.
*/
static SQInteger QueryF(HSQUIRRELVM vm);
};
/* ------------------------------------------------------------------------------------------------
* Used to manage and interact with fields from result-sets.
*/
class MySQLField
2021-06-12 16:51:33 +02:00
{
// --------------------------------------------------------------------------------------------
friend class MySQLResultSet;
2021-06-12 16:51:33 +02:00
private:
// --------------------------------------------------------------------------------------------
uint32_t m_Index; // The actual index of the referenced field.
MySQLResRef m_Handle; // Reference to the actual database result-set.
2021-06-12 16:51:33 +02:00
protected:
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle and field index, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(const char * file, int32_t line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle and field index, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(const char * file, int32_t line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle, field index and row, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateStepped(const char * file, int32_t line) const;
#else
void ValidateStepped() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle and field index, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetValid(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetValid() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle and field index, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetCreated(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetCreated() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle field index and row, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetStepped(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetStepped() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the associated result-set handle and field index, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateField(uint32_t idx, const char * file, int32_t line) const;
#else
void ValidateField(uint32_t idx) const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(uint32_t idx)
{
SQMOD_VALIDATE_FIELD(*this, idx);
// Assign the new index
m_Index = idx;
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(const SQChar * name)
{
SetIndex(SQMOD_GET_CREATED(*this)->GetFieldIndex(name));
}
/* --------------------------------------------------------------------------------------------
* Modify the index to the specified value.
*/
void SetIndex(const Object & field);
public:
// --------------------------------------------------------------------------------------------
static constexpr uint32_t INVALID_INDEX = std::numeric_limits< uint32_t >::max(); // Value that represents an invalid index.
/* --------------------------------------------------------------------------------------------
* Default constructor (null).
*/
MySQLField()
2021-06-12 16:51:33 +02:00
: m_Index(INVALID_INDEX), m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* No field constructor.
*/
explicit MySQLField(const MySQLResRef & rset) // NOLINT(modernize-pass-by-value)
2021-06-12 16:51:33 +02:00
: m_Index(INVALID_INDEX), m_Handle(rset)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Index constructor.
*/
MySQLField(const MySQLResRef & rset, uint32_t idx) // NOLINT(modernize-pass-by-value)
2021-06-12 16:51:33 +02:00
: m_Index(idx), m_Handle(rset)
{
SQMOD_VALIDATE_FIELD(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Name constructor.
*/
MySQLField(const MySQLResRef & rset, const SQChar * name)
2021-06-12 16:51:33 +02:00
: m_Index(rset ? rset->GetFieldIndex(name) : -1), m_Handle(rset)
{
SQMOD_VALIDATE_FIELD(*this, m_Index);
}
/* --------------------------------------------------------------------------------------------
* Dynamic constructor.
*/
MySQLField(const MySQLResRef & rset, const Object & field) // NOLINT(modernize-pass-by-value)
2021-06-12 16:51:33 +02:00
: m_Index(INVALID_INDEX), m_Handle(rset)
{
if (!m_Handle)
{
STHROWF("Invalid MySQL result-set reference");
}
// Extract the index
SetIndex(field);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLField(const MySQLField & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLField(MySQLField && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLField & operator = (const MySQLField & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLField & operator = (MySQLField && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two result-set field indexes.
*/
bool operator == (const MySQLField & o) const
2021-06-12 16:51:33 +02:00
{
return (m_Index == o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two result-set field indexes.
*/
bool operator != (const MySQLField & o) const
2021-06-12 16:51:33 +02:00
{
return (m_Index != o.m_Index);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const // NOLINT(google-explicit-constructor)
{
return (m_Handle && m_Handle->CheckFieldIndex(m_Index));
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
SQMOD_NODISCARD int32_t Cmp(const MySQLField & o) const
2021-06-12 16:51:33 +02:00
{
if (m_Index == o.m_Index)
{
return 0;
}
else if (m_Index > o.m_Index)
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
SQMOD_NODISCARD String ToString() const
{
// Can we attempt to return the parameter name?
if (m_Handle && m_Handle->CheckFieldIndex(m_Index))
{
return m_Handle->mFields[m_Index].name;
}
return fmt::format("{}", m_Index);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether the field is valid.
*/
SQMOD_NODISCARD bool IsValid() const
{
return m_Handle; // An invalid result-set means an invalid field
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to the associated result-set handle.
*/
SQMOD_NODISCARD uint32_t GetRefCount() const
{
return m_Handle.Count();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced field index.
*/
SQMOD_NODISCARD SQInteger GetIndex() const
{
return ConvTo< SQInteger >::From(m_Index);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced database result-set.
*/
SQMOD_NODISCARD Object GetResultSet() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the referenced database connection.
*/
SQMOD_NODISCARD Object GetConnection() const;
/* --------------------------------------------------------------------------------------------
* Release the reference to the referenced database result-set and field index.
*/
void Release()
{
m_Handle.Reset();
m_Index = INVALID_INDEX;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a boolean value.
*/
SQMOD_NODISCARD bool GetBoolean() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a character.
*/
SQMOD_NODISCARD SQChar GetChar() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a native script integer.
*/
SQMOD_NODISCARD SQInteger GetInteger() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a native script floating point.
*/
SQMOD_NODISCARD SQFloat GetFloat() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a signed 8 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt8() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as an unsigned 8 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint8() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a signed 16 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt16() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as an unsigned 16 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint16() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a signed 32 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt32() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as an unsigned 32 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint32() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a signed 64 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt64() const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as an unsigned 64 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint64() const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a 32 bit floating point value.
*/
SQMOD_NODISCARD SQFloat GetFloat32() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a 64 bit floating point value.
*/
SQMOD_NODISCARD SQFloat GetFloat64() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a string value.
*/
SQMOD_NODISCARD Object GetString() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a memory buffer.
*/
SQMOD_NODISCARD Object GetBuffer() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the referenced field as a memory blob.
*/
SQMOD_NODISCARD Object GetBlob() const;
};
/* ------------------------------------------------------------------------------------------------
* Allows management and interaction with a result set handle.
*/
class MySQLResultSet
2021-06-12 16:51:33 +02:00
{
private:
// --------------------------------------------------------------------------------------------
MySQLResRef m_Handle; // Reference to the actual database result-set.
2021-06-12 16:51:33 +02:00
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(const char * file, int32_t line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(const char * file, int32_t line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and row, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateStepped(const char * file, int32_t line) const;
#else
void ValidateStepped() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetValid(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetValid() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetCreated(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetCreated() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and row, and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
SQMOD_NODISCARD const MySQLResRef & GetStepped(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLResRef & GetStepped() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and field index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateField(int32_t idx, const char * file, int32_t line) const;
#else
void ValidateField(int32_t idx) const;
#endif // _DEBUG
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLResultSet()
2021-06-12 16:51:33 +02:00
: m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* MySQLConnection constructor.
2021-06-12 16:51:33 +02:00
*/
explicit MySQLResultSet(const MySQLConnRef & conn)
: m_Handle(new MySQLResHnd())
2021-06-12 16:51:33 +02:00
{
m_Handle->Create(conn);
}
/* --------------------------------------------------------------------------------------------
* MySQLStatement constructor.
2021-06-12 16:51:33 +02:00
*/
explicit MySQLResultSet(const MySQLStmtRef & stmt)
: m_Handle(new MySQLResHnd())
2021-06-12 16:51:33 +02:00
{
m_Handle->Create(stmt);
}
/* --------------------------------------------------------------------------------------------
* Handle constructor.
*/
explicit MySQLResultSet(MySQLResRef hnd)
2021-06-12 16:51:33 +02:00
: m_Handle(std::move(hnd))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLResultSet(const MySQLResultSet & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLResultSet(MySQLResultSet && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLResultSet() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLResultSet & operator = (const MySQLResultSet & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLResultSet & operator = (MySQLResultSet && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
SQMOD_NODISCARD int32_t Cmp(const MySQLResultSet & o) const
2021-06-12 16:51:33 +02:00
{
if (m_Handle.Get() == o.m_Handle.Get())
{
return 0;
}
else if (m_Handle.Get() > o.m_Handle.Get())
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
SQMOD_NODISCARD String ToString() const
{
// Do we have a valid handle?
if (m_Handle)
{
2022-03-16 21:36:50 +01:00
return fmt::format("{}", m_Handle->mFieldCount);
2021-06-12 16:51:33 +02:00
}
// Default to a negative value
return "-1";
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
SQMOD_NODISCARD static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See whether the managed handle is valid.
*/
SQMOD_NODISCARD bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Returns an array with all the field names available in the managed result set.
*/
SQMOD_NODISCARD Array GetFieldNames() const;
/* --------------------------------------------------------------------------------------------
* Returns an array with wrapper instances for all the field available in the managed result set.
*/
SQMOD_NODISCARD Array GetFieldsArray() const;
/* --------------------------------------------------------------------------------------------
* Returns an array with wrapper instances for the specified fields in the managed result set.
*/
SQMOD_NODISCARD Array FetchFieldsArray(Array & fields) const;
/* --------------------------------------------------------------------------------------------
* Returns a table with wrapper instances for all the field available in the managed result set.
*/
SQMOD_NODISCARD Table GetFieldsTable() const;
/* --------------------------------------------------------------------------------------------
* Returns a table with wrapper instances for all the specified fields in the managed result set.
*/
SQMOD_NODISCARD Table FetchFieldsTable(Array & fields) const;
/* --------------------------------------------------------------------------------------------
* Returns the current position of the row cursor for the last Next().
*/
SQMOD_NODISCARD SQInteger RowIndex() const
2021-06-12 16:51:33 +02:00
{
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->RowIndex());
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Returns the number of rows in the result set.
*/
SQMOD_NODISCARD SQInteger RowCount() const
2021-06-12 16:51:33 +02:00
{
return static_cast< SQInteger >(SQMOD_GET_CREATED(*this)->RowCount());
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the next row from the query.
*/
SQMOD_NODISCARD bool Next() const
{
return SQMOD_GET_CREATED(*this)->Next();
}
/* --------------------------------------------------------------------------------------------
* Seeks to an arbitrary row in a query result set.
*/
SQMOD_NODISCARD bool SetRowIndex(SQInteger index) const
{
return SQMOD_GET_CREATED(*this)->SetRowIndex(ConvTo< uint64_t >::From(index));
}
/* --------------------------------------------------------------------------------------------
* Seeks to an arbitrary row in a query result set.
*/
SQMOD_NODISCARD bool SetLongRowIndex(SQInteger index) const
2021-06-12 16:51:33 +02:00
{
return SQMOD_GET_CREATED(*this)->SetRowIndex(static_cast< uint64_t >(index));
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the field with the specified name or index.
*/
SQMOD_NODISCARD MySQLField GetField(const Object & field) const
2021-06-12 16:51:33 +02:00
{
return MySQLField(SQMOD_GET_STEPPED(*this), field);
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a boolean value.
*/
SQMOD_NODISCARD bool GetBoolean(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetBoolean();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a character.
*/
SQMOD_NODISCARD SQChar GetChar(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetChar();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a native script integer.
*/
SQMOD_NODISCARD SQInteger GetInteger(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetInteger();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a native script floating point.
*/
SQMOD_NODISCARD SQFloat GetFloat(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetFloat();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a signed 8 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt8(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetInt8();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as an unsigned 8 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint8(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetUint8();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a signed 16 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt16(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetInt16();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as an unsigned 16 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint16(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetUint16();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a signed 32 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetInt32(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetInt32();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as an unsigned 32 bit integer value.
*/
SQMOD_NODISCARD SQInteger GetUint32(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetUint32();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a signed 64 bit integer value.
*/
SQMOD_NODISCARD Object GetInt64(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetInt64();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as an unsigned 64 bit integer value.
*/
SQMOD_NODISCARD Object GetUint64(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetUint64();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a 32 bit floating point value.
*/
SQMOD_NODISCARD SQFloat GetFloat32(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetFloat32();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a 64 bit floating point value.
*/
SQMOD_NODISCARD SQFloat GetFloat64(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetFloat64();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a string value.
*/
SQMOD_NODISCARD Object GetString(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetString();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a memory buffer.
*/
SQMOD_NODISCARD Object GetBuffer(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetBuffer();
2021-06-12 16:51:33 +02:00
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value inside the specified field as a memory blob.
*/
SQMOD_NODISCARD Object GetBlob(const Object & field) const
{
return MySQLField(SQMOD_GET_STEPPED(*this), field).GetBlob();
2021-06-12 16:51:33 +02:00
}
};
/* ------------------------------------------------------------------------------------------------
* Allows management and interaction with a statement handle.
*/
class MySQLStatement
2021-06-12 16:51:33 +02:00
{
private:
// --------------------------------------------------------------------------------------------
MySQLStmtRef m_Handle; // Reference to the actual database statement.
2021-06-12 16:51:33 +02:00
protected:
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void Validate(const char * file, int32_t line) const;
#else
void Validate() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateCreated(const char * file, int32_t line) const;
#else
void ValidateCreated() const;
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const MySQLStmtRef & GetValid(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLStmtRef & GetValid() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the managed statement handle and throw an error if invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
const MySQLStmtRef & GetCreated(const char * file, int32_t line) const;
2021-06-12 16:51:33 +02:00
#else
SQMOD_NODISCARD const MySQLStmtRef & GetCreated() const;
2021-06-12 16:51:33 +02:00
#endif // _DEBUG
/* --------------------------------------------------------------------------------------------
* Validate the statement reference and parameter index, and throw an error if they're invalid.
*/
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
void ValidateParam(int32_t idx, const char * file, int32_t line) const;
#else
void ValidateParam(int32_t idx) const;
#endif // _DEBUG
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLStatement()
2021-06-12 16:51:33 +02:00
: m_Handle()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Construct a statement under the specified connection using the specified string.
*/
MySQLStatement(const MySQLConnRef & connection, const SQChar * query)
: m_Handle(new MySQLStmtHnd())
2021-06-12 16:51:33 +02:00
{
m_Handle->Create(connection, query);
}
/* --------------------------------------------------------------------------------------------
* Construct a statement under the specified connection using the specified string.
*/
MySQLStatement(const MySQLConnection & connection, const SQChar * query);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLStatement(const MySQLStatement & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLStatement(MySQLStatement && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLStatement & operator = (const MySQLStatement & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLStatement & operator = (MySQLStatement && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
SQMOD_NODISCARD int32_t Cmp(const MySQLStatement & o) const
2021-06-12 16:51:33 +02:00
{
if (m_Handle.Get() == o.m_Handle.Get())
{
return 0;
}
else if (m_Handle.Get() > o.m_Handle.Get())
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
SQMOD_NODISCARD const String & ToString() const
{
// Do we have a valid handle?
if (m_Handle)
{
return m_Handle->mQuery;
2021-06-12 16:51:33 +02:00
}
// Default to an empty string
return NullString();
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
SQMOD_NODISCARD static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated connection handle.
*/
SQMOD_NODISCARD const MySQLStmtRef & GetHandle() const
2021-06-12 16:51:33 +02:00
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* See whether the managed handle is valid.
*/
SQMOD_NODISCARD bool IsValid() const
{
return m_Handle;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the currently associated statement connection.
*/
SQMOD_NODISCARD MySQLConnection GetConnection() const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Modify the currently associated statement connection.
*/
void SetConnection(const MySQLConnection & conn);
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Execute the statement.
*/
SQMOD_NODISCARD int32_t Execute();
/* --------------------------------------------------------------------------------------------
* Execute the statement.
*/
SQMOD_NODISCARD uint32_t Insert();
/* --------------------------------------------------------------------------------------------
* Execute the statement.
*/
SQMOD_NODISCARD MySQLResultSet Query();
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Assign a signed 8bit integer to a parameter.
*/
void SetInt8(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign an unsigned 8bit integer to a parameter.
*/
void SetUint8(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a signed 16bit integer to a parameter.
*/
void SetInt16(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign an unsigned 16bit integer to a parameter.
*/
void SetUint16(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a signed 32bit integer to a parameter.
*/
void SetInt32(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign an unsigned 32bit integer to a parameter.
*/
void SetUint32(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a signed 64bit integer to a parameter.
*/
void SetInt64(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign an unsigned 64bit integer to a parameter.
*/
void SetUint64(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a signed long integer to a parameter.
*/
void SetSLongInt(uint32_t idx, SQInteger val) const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Assign an unsigned long integer to a parameter.
*/
void SetULongInt(uint32_t idx, SQInteger val) const;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Assign a native integer to a parameter.
*/
void SetInteger(uint32_t idx, SQInteger val) const;
/* --------------------------------------------------------------------------------------------
* Assign a 32bit floating point to a parameter.
*/
void SetFloat32(uint32_t idx, SQFloat val) const;
/* --------------------------------------------------------------------------------------------
* Assign a 64bit floating point to a parameter.
*/
void SetFloat64(uint32_t idx, SQFloat val) const;
/* --------------------------------------------------------------------------------------------
* Assign a native float to a parameter.
*/
void SetFloat(uint32_t idx, SQFloat val) const;
/* --------------------------------------------------------------------------------------------
* Assign a boolean to a parameter.
*/
void SetBoolean(uint32_t idx, bool val) const;
/* --------------------------------------------------------------------------------------------
* Assign a date to a parameter.
*/
void SetDate(uint32_t idx, const Date & val) const;
/* --------------------------------------------------------------------------------------------
* Assign a time to a parameter.
*/
void SetTime(uint32_t idx, const Time & val) const;
/* --------------------------------------------------------------------------------------------
* Assign a date and time to a parameter.
*/
void SetDatetime(uint32_t idx, const Datetime & val) const;
/* --------------------------------------------------------------------------------------------
* Assign a string to a parameter.
*/
void SetString(uint32_t idx, const SQChar * val) const;
/* --------------------------------------------------------------------------------------------
* Assign an enumeration to a parameter.
*/
void SetEnum(uint32_t idx, const SQChar * val) const;
/* --------------------------------------------------------------------------------------------
* Assign an enumeration to a parameter.
*/
void SetSet(uint32_t idx, const SQChar * val) const;
/* --------------------------------------------------------------------------------------------
* Assign a blob to a parameter.
*/
void SetBlob(uint32_t idx, Object & val) const;
/* --------------------------------------------------------------------------------------------
* Assign a buffer to a parameter.
*/
void SetData(uint32_t idx, Object & val) const;
/* --------------------------------------------------------------------------------------------
* Assign a null to a parameter.
*/
void SetNull(uint32_t idx) const;
};
/* ------------------------------------------------------------------------------------------------
* ...
*/
struct MySQLParameter
2021-06-12 16:51:33 +02:00
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLParameter() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
MySQLParameter(const MySQLParameter & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
MySQLParameter(MySQLParameter && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLParameter() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
MySQLParameter & operator = (const MySQLParameter & o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
MySQLParameter & operator = (MySQLParameter && o) = default;
2021-06-12 16:51:33 +02:00
};
/* ------------------------------------------------------------------------------------------------
* ...
*/
struct MySQLTransaction
2021-06-12 16:51:33 +02:00
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
MySQLTransaction() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
MySQLTransaction(const MySQLTransaction & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
MySQLTransaction(MySQLTransaction && o) = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~MySQLTransaction() = default;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
MySQLTransaction & operator = (const MySQLTransaction & o) = delete;
2021-06-12 16:51:33 +02:00
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
MySQLTransaction & operator = (MySQLTransaction && o) = default;
2021-06-12 16:51:33 +02:00
};
} // Namespace:: SqMod