sql.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #ifndef SQL_HPP
  4. #define SQL_HPP
  5. #include <cstdarg>// va_list
  6. #include <stdexcept>
  7. #ifdef WIN32
  8. #include "winapi.hpp"
  9. #endif
  10. #include <mysql.h>
  11. #include "cbasetypes.hpp"
  12. #include "strlib.hpp"
  13. // Return codes
  14. #define SQL_ERROR -1
  15. #define SQL_SUCCESS 0
  16. #define SQL_NO_DATA 100
  17. // macro definition to determine whether the mySQL engine is running on InnoDB (rather than MyISAM)
  18. // uncomment this line if the your mySQL tables have been changed to run on InnoDB
  19. // this macro will adjust how logs are recorded in the database to accommodate the change
  20. //#define SQL_INNODB
  21. /// Data type identifier.
  22. /// String, enum and blob data types need the buffer length specified.
  23. enum SqlDataType
  24. {
  25. SQLDT_NULL,
  26. // fixed size
  27. SQLDT_INT8,
  28. SQLDT_INT16,
  29. SQLDT_INT32,
  30. SQLDT_INT64,
  31. SQLDT_UINT8,
  32. SQLDT_UINT16,
  33. SQLDT_UINT32,
  34. SQLDT_UINT64,
  35. // platform dependent size
  36. SQLDT_CHAR,
  37. SQLDT_LONG,
  38. SQLDT_LONGLONG,
  39. SQLDT_UCHAR,
  40. SQLDT_ULONG,
  41. SQLDT_ULONGLONG,
  42. // floating point
  43. SQLDT_FLOAT,
  44. SQLDT_DOUBLE,
  45. // other
  46. SQLDT_STRING,
  47. SQLDT_ENUM,
  48. // Note: An ENUM is a string with restricted values. When an invalid value
  49. // is inserted, it is saved as an empty string (numerical value 0).
  50. SQLDT_BLOB,
  51. SQLDT_LASTID
  52. };
  53. struct Sql;// Sql handle (private access)
  54. typedef enum SqlDataType SqlDataType;
  55. typedef struct Sql Sql;
  56. /// Allocates and initializes a new Sql handle.
  57. struct Sql* Sql_Malloc(void);
  58. /// Retrieves the last error number.
  59. uint32 Sql_GetError( Sql* self );
  60. /// Establishes a connection.
  61. ///
  62. /// @return SQL_SUCCESS or SQL_ERROR
  63. int32 Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db);
  64. /// Retrieves the timeout of the connection.
  65. ///
  66. /// @return SQL_SUCCESS or SQL_ERROR
  67. int32 Sql_GetTimeout(Sql* self, uint32* out_timeout);
  68. /// Retrieves the name of the columns of a table into out_buf, with the separator after each name.
  69. ///
  70. /// @return SQL_SUCCESS or SQL_ERROR
  71. int32 Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep);
  72. /// Changes the encoding of the connection.
  73. ///
  74. /// @return SQL_SUCCESS or SQL_ERROR
  75. int32 Sql_SetEncoding(Sql* self, const char* encoding);
  76. /// Pings the connection.
  77. ///
  78. /// @return SQL_SUCCESS or SQL_ERROR
  79. int32 Sql_Ping(Sql* self);
  80. /// Escapes a string.
  81. /// The output buffer must be at least strlen(from)*2+1 in size.
  82. ///
  83. /// @return The size of the escaped string
  84. size_t Sql_EscapeString(Sql* self, char* out_to, const char* from);
  85. /// Escapes a string.
  86. /// The output buffer must be at least from_len*2+1 in size.
  87. ///
  88. /// @return The size of the escaped string
  89. size_t Sql_EscapeStringLen(Sql* self, char* out_to, const char* from, size_t from_len);
  90. /// Executes a query.
  91. /// Any previous result is freed.
  92. /// The query is constructed as if it was sprintf.
  93. ///
  94. /// @return SQL_SUCCESS or SQL_ERROR
  95. int32 Sql_Query(Sql* self, const char* query, ...);
  96. /// Executes a query.
  97. /// Any previous result is freed.
  98. /// The query is constructed as if it was svprintf.
  99. ///
  100. /// @return SQL_SUCCESS or SQL_ERROR
  101. int32 Sql_QueryV(Sql* self, const char* query, va_list args);
  102. /// Executes a query.
  103. /// Any previous result is freed.
  104. /// The query is used directly.
  105. ///
  106. /// @return SQL_SUCCESS or SQL_ERROR
  107. int32 Sql_QueryStr(Sql* self, const char* query);
  108. /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query.
  109. ///
  110. /// @return Value of the auto-increment column
  111. uint64 Sql_LastInsertId(Sql* self);
  112. /// Returns the number of columns in each row of the result.
  113. ///
  114. /// @return Number of columns
  115. uint32 Sql_NumColumns(Sql* self);
  116. /// Returns the number of rows in the result.
  117. ///
  118. /// @return Number of rows
  119. uint64 Sql_NumRows(Sql* self);
  120. /// Returns the number of rows affected by the last query
  121. ///
  122. /// @return Number of rows
  123. uint64 Sql_NumRowsAffected(Sql* self);
  124. /// Fetches the next row.
  125. /// The data of the previous row is no longer valid.
  126. ///
  127. /// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
  128. int32 Sql_NextRow(Sql* self);
  129. /// Gets the data of a column.
  130. /// The data remains valid until the next row is fetched or the result is freed.
  131. ///
  132. /// @return SQL_SUCCESS or SQL_ERROR
  133. int32 Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len);
  134. /// Frees the result of the query.
  135. void Sql_FreeResult(Sql* self);
  136. #if defined(SQL_REMOVE_SHOWDEBUG)
  137. #define Sql_ShowDebug(self) (void)0
  138. #else
  139. #define Sql_ShowDebug(self) Sql_ShowDebug_(self, __FILE__, __LINE__)
  140. #endif
  141. /// Shows debug information (last query).
  142. void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line);
  143. /// Frees a Sql handle returned by Sql_Malloc.
  144. void Sql_Free(Sql* self);
  145. // Column length receiver.
  146. // Takes care of the possible size missmatch between uint32 and unsigned long.
  147. struct s_column_length
  148. {
  149. uint32* out_length;
  150. unsigned long length;
  151. };
  152. typedef struct s_column_length s_column_length;
  153. ///////////////////////////////////////////////////////////////////////////////
  154. // Prepared Statements
  155. ///////////////////////////////////////////////////////////////////////////////
  156. // Parameters are placed in the statement by embedding question mark ('?')
  157. // characters into the query at the appropriate positions.
  158. // The markers are legal only in places where they represent data.
  159. // The markers cannot be inside quotes. Quotes will be added automatically
  160. // when they are required.
  161. //
  162. // example queries with parameters:
  163. // 1) SELECT col FROM table WHERE id=?
  164. // 2) INSERT INTO table(col1,col2) VALUES(?,?)
  165. class SqlStmt{
  166. private:
  167. StringBuf buf;
  168. MYSQL_STMT* stmt;
  169. MYSQL_BIND* params;
  170. MYSQL_BIND* columns;
  171. s_column_length* column_lengths;
  172. size_t max_params;
  173. size_t max_columns;
  174. bool bind_params;
  175. bool bind_columns;
  176. void ShowDebugTruncatedColumn( size_t i );
  177. public:
  178. explicit SqlStmt( Sql& sql ) noexcept(false);
  179. ~SqlStmt();
  180. /// Prepares the statement.
  181. /// Any previous result is freed and all parameter bindings are removed.
  182. /// The query is constructed as if it was sprintf.
  183. ///
  184. /// @return SQL_SUCCESS or SQL_ERROR
  185. int32 Prepare( const char* query, ... );
  186. /// Prepares the statement.
  187. /// Any previous result is freed and all parameter bindings are removed.
  188. /// The query is constructed as if it was svprintf.
  189. ///
  190. /// @return SQL_SUCCESS or SQL_ERROR
  191. int32 PrepareV( const char* query, va_list args );
  192. /// Prepares the statement.
  193. /// Any previous result is freed and all parameter bindings are removed.
  194. /// The query is used directly.
  195. ///
  196. /// @return SQL_SUCCESS or SQL_ERROR
  197. int32 PrepareStr( const char* query );
  198. /// Returns the number of parameters in the prepared statement.
  199. ///
  200. /// @return Number or paramenters
  201. size_t NumParams();
  202. /// Binds a parameter to a buffer.
  203. /// The buffer data will be used when the statement is executed.
  204. /// All parameters should have bindings.
  205. ///
  206. /// @return SQL_SUCCESS or SQL_ERROR
  207. int32 BindParam( size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len );
  208. /// Executes the prepared statement.
  209. /// Any previous result is freed and all column bindings are removed.
  210. ///
  211. /// @return SQL_SUCCESS or SQL_ERROR
  212. int32 Execute();
  213. /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement.
  214. ///
  215. /// @return Value of the auto-increment column
  216. uint64 LastInsertId();
  217. /// Returns the number of columns in each row of the result.
  218. ///
  219. /// @return Number of columns
  220. size_t NumColumns();
  221. /// Binds the result of a column to a buffer.
  222. /// The buffer will be filled with data when the next row is fetched.
  223. /// For string/enum buffer types there has to be enough space for the data
  224. /// and the nul-terminator (an extra byte).
  225. ///
  226. /// @return SQL_SUCCESS or SQL_ERROR
  227. int32 BindColumn( size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null );
  228. /// Returns the number of rows in the result.
  229. ///
  230. /// @return Number of rows
  231. uint64 NumRows();
  232. /// Fetches the next row.
  233. /// All column bindings will be filled with data.
  234. ///
  235. /// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
  236. int32 NextRow();
  237. /// Frees the result of the statement execution.
  238. void FreeResult();
  239. void ShowDebug_( const char* file, const unsigned long line );
  240. };
  241. #if defined(SQL_REMOVE_SHOWDEBUG)
  242. #define SqlStmt_ShowDebug(self) (void)0
  243. #else
  244. // TODO: we have to keep this until C++20 and std::source_location is available [Lemongrass]
  245. #define SqlStmt_ShowDebug(self) (self).ShowDebug_( __FILE__, __LINE__ )
  246. #endif
  247. void Sql_Init(void);
  248. #endif /* SQL_HPP */