| 1 | #ifndef ENGINE_SERVER_DATABASES_CONNECTION_H |
| 2 | #define ENGINE_SERVER_DATABASES_CONNECTION_H |
| 3 | |
| 4 | #include "connection_pool.h" |
| 5 | |
| 6 | #include <engine/shared/protocol.h> |
| 7 | |
| 8 | #include <memory> |
| 9 | |
| 10 | enum |
| 11 | { |
| 12 | // MAX_NAME_LENGTH includes the size with \0, which is not necessary in SQL |
| 13 | MAX_NAME_LENGTH_SQL = MAX_NAME_LENGTH - 1, |
| 14 | }; |
| 15 | |
| 16 | class IConsole; |
| 17 | |
| 18 | // can hold one PreparedStatement with Results |
| 19 | class IDbConnection |
| 20 | { |
| 21 | public: |
| 22 | IDbConnection(const char *pPrefix); |
| 23 | virtual ~IDbConnection() = default; |
| 24 | IDbConnection &operator=(const IDbConnection &) = delete; |
| 25 | virtual void Print(IConsole *pConsole, const char *pMode) = 0; |
| 26 | |
| 27 | // returns the database prefix |
| 28 | const char *GetPrefix() const { return m_aPrefix; } |
| 29 | virtual const char *BinaryCollate() const = 0; |
| 30 | // can be inserted into queries to convert a timestamp variable to the unix timestamp |
| 31 | virtual void ToUnixTimestamp(const char *pTimestamp, char *aBuf, unsigned int BufferSize) = 0; |
| 32 | // since MySQL automatically converts timestamps to utc, meanwhile sqlite code has to |
| 33 | // explicitly convert before inserting timestamps, NOTE: CURRENT_TIMESTAMP in SQLite is UTC by |
| 34 | // default and doesn't have to be converted |
| 35 | virtual const char *InsertTimestampAsUtc() const = 0; |
| 36 | // can be used in the context of `LIKE Map`, adds `? COLLATE` |
| 37 | virtual const char *CollateNocase() const = 0; |
| 38 | // syntax to insert a row into table or ignore if it already exists |
| 39 | virtual const char *InsertIgnore() const = 0; |
| 40 | // ORDER BY RANDOM()/RAND() |
| 41 | virtual const char *Random() const = 0; |
| 42 | // Get Median Map Time from l.Map |
| 43 | virtual const char *MedianMapTime(char *pBuffer, int BufferSize) const = 0; |
| 44 | virtual const char *False() const = 0; |
| 45 | virtual const char *True() const = 0; |
| 46 | |
| 47 | // tries to allocate the connection from the pool established |
| 48 | // |
| 49 | // returns true on success |
| 50 | virtual bool Connect(char *pError, int ErrorSize) = 0; |
| 51 | // has to be called to return the connection back to the pool |
| 52 | virtual void Disconnect() = 0; |
| 53 | |
| 54 | // ? for Placeholders, connection has to be established, can overwrite previous prepared statements |
| 55 | // |
| 56 | // returns true on success |
| 57 | virtual bool PrepareStatement(const char *pStmt, char *pError, int ErrorSize) = 0; |
| 58 | |
| 59 | // PrepareStatement has to be called beforehand, |
| 60 | virtual void BindString(int Idx, const char *pString) = 0; |
| 61 | virtual void BindBlob(int Idx, unsigned char *pBlob, int Size) = 0; |
| 62 | virtual void BindInt(int Idx, int Value) = 0; |
| 63 | virtual void BindInt64(int Idx, int64_t Value) = 0; |
| 64 | virtual void BindFloat(int Idx, float Value) = 0; |
| 65 | virtual void BindNull(int Idx) = 0; |
| 66 | |
| 67 | // Print expanded sql statement |
| 68 | virtual void Print() = 0; |
| 69 | |
| 70 | // executes the query and returns if a result row exists and selects it |
| 71 | // when called multiple times the next row is selected |
| 72 | // |
| 73 | // returns true on success |
| 74 | virtual bool Step(bool *pEnd, char *pError, int ErrorSize) = 0; |
| 75 | // executes the query and returns the number of rows affected by the update/insert/delete |
| 76 | // |
| 77 | // returns true on success |
| 78 | virtual bool ExecuteUpdate(int *pNumUpdated, char *pError, int ErrorSize) = 0; |
| 79 | |
| 80 | virtual bool IsNull(int Col) = 0; |
| 81 | virtual float GetFloat(int Col) = 0; |
| 82 | virtual int GetInt(int Col) = 0; |
| 83 | virtual int64_t GetInt64(int Col) = 0; |
| 84 | // ensures that the string is null terminated |
| 85 | virtual void GetString(int Col, char *pBuffer, int BufferSize) = 0; |
| 86 | // returns number of bytes read into the buffer |
| 87 | virtual int GetBlob(int Col, unsigned char *pBuffer, int BufferSize) = 0; |
| 88 | |
| 89 | // SQL statements, that can't be abstracted, has side effects to the result |
| 90 | virtual bool AddPoints(const char *pPlayer, int Points, char *pError, int ErrorSize) = 0; |
| 91 | |
| 92 | private: |
| 93 | char m_aPrefix[64]; |
| 94 | |
| 95 | protected: |
| 96 | void FormatCreateRace(char *aBuf, unsigned int BufferSize, bool Backup) const; |
| 97 | void FormatCreateTeamrace(char *aBuf, unsigned int BufferSize, const char *pIdType, bool Backup) const; |
| 98 | void FormatCreateMaps(char *aBuf, unsigned int BufferSize) const; |
| 99 | void FormatCreateSaves(char *aBuf, unsigned int BufferSize, bool Backup) const; |
| 100 | void FormatCreatePoints(char *aBuf, unsigned int BufferSize) const; |
| 101 | }; |
| 102 | |
| 103 | bool MysqlAvailable(); |
| 104 | int MysqlInit(); |
| 105 | void MysqlUninit(); |
| 106 | |
| 107 | std::unique_ptr<IDbConnection> CreateSqliteConnection(const char *pFilename, bool Setup); |
| 108 | // Returns nullptr if MySQL support is not compiled in. |
| 109 | std::unique_ptr<IDbConnection> CreateMysqlConnection(CMysqlConfig Config); |
| 110 | |
| 111 | #endif // ENGINE_SERVER_DATABASES_CONNECTION_H |
| 112 | |