PageRenderTime 37ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/ext/mysql/mysql_common.h

http://github.com/facebook/hiphop-php
C Header | 478 lines | 335 code | 92 blank | 51 comment | 4 complexity | 828e4edf3d9e8aee6e1049bacde0c726 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #ifndef incl_HPHP_MYSQL_COMMON_H_
  18. #define incl_HPHP_MYSQL_COMMON_H_
  19. #include "hphp/runtime/base/req-list.h"
  20. #include "hphp/runtime/base/req-optional.h"
  21. #include "hphp/runtime/base/req-vector.h"
  22. #include "hphp/runtime/base/request-event-handler.h"
  23. #include "hphp/runtime/ext/extension.h"
  24. #include "mysql.h"
  25. #ifdef ENABLE_ASYNC_MYSQL
  26. #include "squangle/mysql_client/SSLOptionsProviderBase.h"
  27. #endif
  28. #ifdef PHP_MYSQL_UNIX_SOCK_ADDR
  29. #ifdef MYSQL_UNIX_ADDR
  30. #undef MYSQL_UNIX_ADDR
  31. #endif
  32. #define MYSQL_UNIX_ADDR PHP_MYSQL_UNIX_SOCK_ADDR
  33. #endif
  34. namespace HPHP {
  35. ///////////////////////////////////////////////////////////////////////////////
  36. #if MYSQL_VERSION_ID >= 80004
  37. using my_bool = bool;
  38. #endif
  39. struct MySQLUtil {
  40. enum TimeoutType { ConnectTimeout, ReadTimeout, WriteTimeout };
  41. static int
  42. set_mysql_timeout(MYSQL* mysql, MySQLUtil::TimeoutType type, int ms);
  43. };
  44. enum class MySQLState : int8_t {
  45. CLOSED = 0,
  46. INITED = 1,
  47. CONNECTED = 2
  48. };
  49. struct MySQL {
  50. /////////////////////////////////////////////////////////////////////////////
  51. MySQL(const char *host, int port, const char *username,
  52. const char *password, const char *database,
  53. MYSQL* raw_connection = nullptr);
  54. ~MySQL() { close(); }
  55. void setLastError(const char *func);
  56. void close();
  57. bool connect(const String& host, int port,
  58. const String& socket,
  59. const String& username,
  60. const String& password,
  61. const String& database,
  62. int client_flags,
  63. int connect_timeout);
  64. bool reconnect(const String& host, int port,
  65. const String& socket,
  66. const String& username,
  67. const String& password,
  68. const String& database,
  69. int client_flags,
  70. int connect_timeout);
  71. /////////////////////////////////////////////////////////////////////////////
  72. bool isPersistent() { return m_persistent; }
  73. void setPersistent() { m_persistent = true; }
  74. MySQLState getState() { return m_state; }
  75. MYSQL* get() { return m_conn;}
  76. MYSQL* eject_mysql() {
  77. auto ret = m_conn;
  78. m_conn = nullptr;
  79. return ret;
  80. }
  81. /////////////////////////////////////////////////////////////////////////////
  82. /**
  83. * Operations on a resource object.
  84. */
  85. static std::shared_ptr<MySQL> Get(const Variant& link_identifier);
  86. static MYSQL* GetConn(const Variant& link_identifier,
  87. std::shared_ptr<MySQL>* rconn = nullptr);
  88. static bool CloseConn(const Variant& link_identifier);
  89. /**
  90. * Default settings.
  91. */
  92. static String GetDefaultServer() { return String();}
  93. static int GetDefaultPort();
  94. static String GetDefaultSocket();
  95. static String GetDefaultUsername() { return String();}
  96. static String GetDefaultPassword() { return String();}
  97. static String GetDefaultDatabase() { return String();}
  98. /**
  99. * A connection may be persistent across multiple HTTP requests.
  100. */
  101. static std::shared_ptr<MySQL> GetPersistent(const String& host, int port,
  102. const String& socket,
  103. const String& username,
  104. const String& password,
  105. int client_flags) {
  106. return GetCachedImpl(host, port, socket, username, password, client_flags);
  107. }
  108. static void SetPersistent(const String& host, int port,
  109. const String& socket,
  110. const String& username,
  111. const String& password,
  112. int client_flags,
  113. const std::shared_ptr<MySQL>& conn) {
  114. SetCachedImpl(host, port, socket, username, password, client_flags, conn);
  115. }
  116. /**
  117. * If connection object is not provided, a default connection will be used.
  118. */
  119. static std::shared_ptr<MySQL> GetDefaultConn();
  120. static void SetDefaultConn(std::shared_ptr<MySQL> conn);
  121. static int GetDefaultReadTimeout();
  122. static void SetDefaultReadTimeout(int timeout_ms);
  123. static size_t NumCachedConnections();
  124. /////////////////////////////////////////////////////////////////////////////
  125. private:
  126. static int s_default_port;
  127. static bool s_allow_reconnect;
  128. static bool s_allow_persistent;
  129. static int s_cur_num_persistent;
  130. static int s_max_num_persistent;
  131. static const std::string s_persistent_type;
  132. static std::string GetHash(const String& host, int port,
  133. const String& socket,
  134. const String& username,
  135. const String& password,
  136. int client_flags);
  137. static std::shared_ptr<MySQL> GetCachedImpl(const String& host, int port,
  138. const String& socket,
  139. const String& username,
  140. const String& password,
  141. int client_flags);
  142. static void SetCachedImpl(const String& host, int port,
  143. const String& socket,
  144. const String& username,
  145. const String& password,
  146. int client_flags,
  147. std::shared_ptr<MySQL> conn);
  148. /////////////////////////////////////////////////////////////////////////////
  149. public:
  150. // Global MySQL settings
  151. static bool IsAllowReconnect() { return s_allow_reconnect; }
  152. static void SetAllowReconnect(bool allow_reconnect) {
  153. s_allow_reconnect = allow_reconnect;
  154. }
  155. static bool IsAllowPersistent() { return s_allow_persistent; }
  156. static void SetAllowPersistent(bool allow_persistent) {
  157. s_allow_persistent = allow_persistent;
  158. }
  159. static int GetMaxNumPersistent() { return s_max_num_persistent; }
  160. static void SetMaxNumPersistent(int max_num_persistent) {
  161. s_max_num_persistent = max_num_persistent;
  162. }
  163. // Ongoing settings
  164. static int GetCurrentNumPersistent() { return s_cur_num_persistent; }
  165. static void SetCurrentNumPersistent(int num) {
  166. s_cur_num_persistent = num;
  167. }
  168. private:
  169. MYSQL* m_conn;
  170. bool m_persistent{false};
  171. public:
  172. std::string m_host;
  173. int m_port;
  174. std::string m_username;
  175. std::string m_password;
  176. std::string m_database;
  177. std::string m_socket;
  178. bool m_last_error_set;
  179. int m_last_errno;
  180. std::string m_last_error;
  181. int m_xaction_count;
  182. bool m_multi_query;
  183. MySQLState m_state;
  184. std::string m_async_query;
  185. };
  186. ///////////////////////////////////////////////////////////////////////////////
  187. struct MySQLResource : SweepableResourceData {
  188. explicit MySQLResource(std::shared_ptr<MySQL> mysql) : m_mysql(mysql) {
  189. assertx(mysql);
  190. }
  191. CLASSNAME_IS("mysql link")
  192. DECLARE_RESOURCE_ALLOCATION(MySQLResource);
  193. // overriding ResourceData
  194. const String& o_getClassNameHook() const override { return classnameof(); }
  195. bool isInvalid() const override { return m_mysql->get() == nullptr; }
  196. std::shared_ptr<MySQL> mysql() const { return m_mysql; }
  197. private:
  198. std::shared_ptr<MySQL> m_mysql;
  199. };
  200. ///////////////////////////////////////////////////////////////////////////////
  201. struct MySQLRequestData final : RequestEventHandler {
  202. void requestInit() override;
  203. void requestShutdown() override {
  204. defaultConn.reset();
  205. totalRowCount = 0;
  206. }
  207. req::ptr<MySQLResource> defaultConn;
  208. int readTimeout;
  209. int totalRowCount; // from all queries in current request
  210. static MySQLRequestData s_mysql_data;
  211. };
  212. ///////////////////////////////////////////////////////////////////////////////
  213. struct MySQLFieldInfo {
  214. String name;
  215. String org_name;
  216. String table;
  217. String org_table;
  218. String def;
  219. String db;
  220. int64_t max_length{0};
  221. int64_t length{0};
  222. int type{0};
  223. unsigned int flags{0};
  224. unsigned int decimals{0};
  225. unsigned int charsetnr{0};
  226. };
  227. ///////////////////////////////////////////////////////////////////////////////
  228. struct MySQLResult : SweepableResourceData {
  229. DECLARE_RESOURCE_ALLOCATION(MySQLResult);
  230. explicit MySQLResult(MYSQL_RES *res, bool localized = false);
  231. ~MySQLResult() override;
  232. CLASSNAME_IS("mysql result")
  233. // overriding ResourceData
  234. const String& o_getClassNameHook() const override { return classnameof(); }
  235. void close() {
  236. sweep();
  237. if (isLocalized()) {
  238. m_rows.reset();
  239. }
  240. }
  241. bool isInvalid() const override {
  242. if (isLocalized()) {
  243. return !m_rows.has_value();
  244. }
  245. return m_res == nullptr;
  246. }
  247. MYSQL_RES *get() {
  248. return m_res;
  249. }
  250. bool isLocalized() const {
  251. return m_localized;
  252. }
  253. void addRow();
  254. void addField(Variant&& value);
  255. void setFieldCount(int64_t fields);
  256. void setFieldInfo(int64_t f, MYSQL_FIELD *field);
  257. MySQLFieldInfo *getFieldInfo(int64_t field);
  258. /**
  259. * Gets the field content. Only for localized result.
  260. */
  261. Variant getField(int64_t field) const;
  262. int64_t getFieldCount() const;
  263. int64_t getRowCount() const;
  264. bool seekRow(int64_t row);
  265. bool fetchRow();
  266. bool isRowReady() const {
  267. return m_row_ready;
  268. }
  269. bool seekField(int64_t field);
  270. int64_t tellField();
  271. MySQLFieldInfo *fetchFieldInfo();
  272. void setAsyncConnection(const std::shared_ptr<MySQL>& conn) {
  273. m_conn = conn;
  274. }
  275. protected:
  276. MYSQL_RES *m_res;
  277. MYSQL_ROW m_current_async_row;
  278. bool m_localized; // whether all the rows have been localized
  279. req::vector<MySQLFieldInfo> m_fields;
  280. req::Optional<req::list<req::vector<Variant>>> m_rows;
  281. req::list<req::vector<Variant>>::const_iterator m_current_row;
  282. int64_t m_current_field;
  283. bool m_row_ready; // set to false after seekRow, true after fetchRow
  284. int64_t m_row_count;
  285. std::shared_ptr<MySQL> m_conn; // only set for async for
  286. // refcounting underlying buffers
  287. };
  288. ///////////////////////////////////////////////////////////////////////////////
  289. struct MySQLStmt : public SweepableResourceData {
  290. DECLARE_RESOURCE_ALLOCATION(MySQLStmt);
  291. explicit MySQLStmt(MYSQL *mysql);
  292. ~MySQLStmt() override;
  293. CLASSNAME_IS("mysql stmt")
  294. // overriding ResourceData
  295. const String& o_getClassNameHook() const override { return classnameof(); }
  296. Variant close();
  297. MYSQL_STMT *get() { return m_stmt; }
  298. Variant affected_rows();
  299. Variant attr_get(int64_t attr);
  300. Variant attr_set(int64_t attr, int64_t value);
  301. Variant data_seek(int64_t offset);
  302. Variant get_errno();
  303. Variant get_error();
  304. Variant execute();
  305. Variant fetch();
  306. Variant field_count();
  307. Variant free_result();
  308. Variant insert_id();
  309. Variant num_rows();
  310. Variant param_count();
  311. Variant prepare(const String& query);
  312. Variant reset();
  313. Variant result_metadata();
  314. Variant send_long_data(int64_t param_idx, const String& data);
  315. Variant sqlstate();
  316. Variant store_result();
  317. protected:
  318. MYSQL_STMT *m_stmt;
  319. bool m_prepared;
  320. };
  321. ///////////////////////////////////////////////////////////////////////////////
  322. // helper
  323. req::ptr<MySQLResult> php_mysql_extract_result(const Resource& result);
  324. req::ptr<MySQLResult> php_mysql_extract_result(const Variant& result);
  325. enum MySQLFieldEntryType { NAME, TABLE, LEN, TYPE, FLAGS };
  326. #define PHP_MYSQL_FIELD_NAME 1
  327. #define PHP_MYSQL_FIELD_TABLE 2
  328. #define PHP_MYSQL_FIELD_LEN 3
  329. #define PHP_MYSQL_FIELD_TYPE 4
  330. #define PHP_MYSQL_FIELD_FLAGS 5
  331. Variant php_mysql_field_info(const Resource& result, int field, int entry_type);
  332. Variant php_mysql_do_connect_on_link(
  333. std::shared_ptr<MySQL> mySQL,
  334. String server,
  335. String username,
  336. String password,
  337. String database,
  338. int client_flags,
  339. bool persistent,
  340. int connect_timeout_ms,
  341. int query_timeout_ms,
  342. const Array* conn_attrs = nullptr
  343. #ifdef ENABLE_ASYNC_MYSQL
  344. , std::shared_ptr<facebook::common::mysql_client::SSLOptionsProviderBase>
  345. ssl_opts = nullptr
  346. #endif
  347. );
  348. Variant php_mysql_do_connect(
  349. const String& server,
  350. const String& username,
  351. const String& password,
  352. const String& database,
  353. int client_flags,
  354. bool persistent,
  355. int connect_timeout_ms,
  356. int query_timeout_ms,
  357. const Array* conn_attrs = nullptr);
  358. Variant php_mysql_do_connect_with_ssl(
  359. const String& server,
  360. const String& username,
  361. const String& password,
  362. const String& database,
  363. int client_flags,
  364. int connect_timeout_ms,
  365. int query_timeout_ms,
  366. const Array* conn_attrs,
  367. const Variant& sslContextProvider /* = null */);
  368. enum MySQLQueryReturn { FAIL = 0, OK = 1, OK_FETCH_RESULT = 2 };
  369. MySQLQueryReturn php_mysql_do_query(
  370. const String& query,
  371. const Variant& link_id);
  372. Variant php_mysql_get_result(const Variant& link_id, bool use_store);
  373. Variant php_mysql_do_query_and_get_result(
  374. const String& query,
  375. const Variant& link_id,
  376. bool use_store);
  377. #define PHP_MYSQL_ASSOC 1 << 0
  378. #define PHP_MYSQL_NUM 1 << 1
  379. #define PHP_MYSQL_BOTH (PHP_MYSQL_ASSOC|PHP_MYSQL_NUM)
  380. Variant php_mysql_fetch_hash(const Resource& result, int result_type);
  381. Variant mysql_makevalue(const String& data, MYSQL_FIELD *mysql_field);
  382. Variant mysql_makevalue(const String& data, enum_field_types field_type);
  383. const char *php_mysql_get_field_name(int field_type);
  384. ///////////////////////////////////////////////////////////////////////////////
  385. }
  386. #endif // incl_HPHP_MYSQL_COMMON_H_