db_driver_mysqli.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Discuz! Team
  4. * This is NOT a freeware, use is subject to license terms
  5. * https://license.discuz.vip
  6. */
  7. if(!defined('IN_DISCUZ')) {
  8. exit('Access Denied');
  9. }
  10. class db_driver_mysqli {
  11. var $tablepre;
  12. var $version = '';
  13. var $drivertype = 'mysqli';
  14. var $querynum = 0;
  15. var $slaveid = 0;
  16. var $curlink;
  17. var $link = [];
  18. var $config = [];
  19. var $sqldebug = [];
  20. var $map = [];
  21. function db_mysql($config = []) {
  22. if(!empty($config)) {
  23. $this->set_config($config);
  24. }
  25. }
  26. function set_config($config) {
  27. $this->config = &$config;
  28. $this->tablepre = $config['1']['tablepre'];
  29. if(!empty($this->config['map'])) {
  30. $this->map = $this->config['map'];
  31. for($i = 1; $i <= 100; $i++) {
  32. if(isset($this->map['forum_thread'])) {
  33. $this->map['forum_thread_'.$i] = $this->map['forum_thread'];
  34. }
  35. if(isset($this->map['forum_post'])) {
  36. $this->map['forum_post_'.$i] = $this->map['forum_post'];
  37. }
  38. if(isset($this->map['forum_attachment']) && $i <= 10) {
  39. $this->map['forum_attachment_'.($i - 1)] = $this->map['forum_attachment'];
  40. }
  41. }
  42. if(isset($this->map['common_member'])) {
  43. $this->map['common_member_archive'] =
  44. $this->map['common_member_count'] = $this->map['common_member_count_archive'] =
  45. $this->map['common_member_status'] = $this->map['common_member_status_archive'] =
  46. $this->map['common_member_profile'] = $this->map['common_member_profile_archive'] =
  47. $this->map['common_member_field_forum'] = $this->map['common_member_field_forum_archive'] =
  48. $this->map['common_member_field_home'] = $this->map['common_member_field_home_archive'] =
  49. $this->map['common_member_validate'] = $this->map['common_member_verify'] =
  50. $this->map['common_member_verify_info'] = $this->map['common_member'];
  51. }
  52. }
  53. }
  54. function connect($serverid = 1) {
  55. if(empty($this->config) || empty($this->config[$serverid])) {
  56. $this->halt('config_db_not_found');
  57. }
  58. $this->link[$serverid] = $this->_dbconnect(
  59. $this->config[$serverid]['dbhost'],
  60. $this->config[$serverid]['dbuser'],
  61. $this->config[$serverid]['dbpw'],
  62. $this->config[$serverid]['dbcharset'],
  63. $this->config[$serverid]['dbname'],
  64. $this->config[$serverid]['pconnect']
  65. );
  66. $this->curlink = $this->link[$serverid];
  67. }
  68. function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect, $halt = true) {
  69. mysqli_report(MYSQLI_REPORT_OFF);
  70. if(intval($pconnect) === 1) $dbhost = 'p:'.$dbhost; // 前面加p:,表示persistent connection
  71. $link = new mysqli();
  72. if(!$link->real_connect($dbhost, $dbuser, $dbpw, $dbname, null, null, MYSQLI_CLIENT_COMPRESS)) {
  73. $halt && $this->halt('notconnect', $this->errno());
  74. } else {
  75. $this->curlink = $link;
  76. $link->options(MYSQLI_OPT_LOCAL_INFILE, false);
  77. $link->set_charset($dbcharset ? $dbcharset : $this->config[1]['dbcharset']);
  78. $serverset = 'sql_mode=\'\',';
  79. $serverset .= 'character_set_client=binary';
  80. $serverset && $link->query("SET $serverset");
  81. }
  82. return $link;
  83. }
  84. function table_name($tablename) {
  85. if(!empty($this->map) && !empty($this->map[$tablename])) {
  86. $id = $this->map[$tablename];
  87. if(!$this->link[$id]) {
  88. $this->connect($id);
  89. }
  90. $this->curlink = $this->link[$id];
  91. } else {
  92. $this->curlink = $this->link[1];
  93. }
  94. return $this->tablepre.$tablename;
  95. }
  96. function select_db($dbname) {
  97. return $this->curlink->select_db($dbname);
  98. }
  99. function fetch_array($query, $result_type = MYSQLI_ASSOC) {
  100. return $query ? $query->fetch_array($result_type) : null;
  101. }
  102. function fetch_first($sql) {
  103. return $this->fetch_array($this->query($sql));
  104. }
  105. function result_first($sql) {
  106. return $this->result($this->query($sql), 0);
  107. }
  108. public function query($sql, $silent = false, $unbuffered = false) {
  109. if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  110. $starttime = microtime(true);
  111. }
  112. if('UNBUFFERED' === $silent) {
  113. $silent = false;
  114. $unbuffered = true;
  115. } elseif('SILENT' === $silent) {
  116. $silent = true;
  117. $unbuffered = false;
  118. }
  119. $resultmode = $unbuffered ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT;
  120. if(!($query = $this->curlink->query($sql, $resultmode))) {
  121. if(in_array($this->errno(), [2006, 2013]) && !str_starts_with($silent, 'RETRY')) {
  122. $this->connect();
  123. return $this->query($sql, 'RETRY'.$silent);
  124. }
  125. if(!$silent) {
  126. $this->halt($this->error(), $this->errno(), $sql);
  127. }
  128. }
  129. if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  130. $this->sqldebug[] = [$sql, number_format((microtime(true) - $starttime), 6), debug_backtrace(), $this->curlink];
  131. }
  132. $this->querynum++;
  133. return $query;
  134. }
  135. function affected_rows() {
  136. return $this->curlink->affected_rows;
  137. }
  138. function error() {
  139. return $this->curlink->error;
  140. }
  141. function errno() {
  142. return $this->curlink->errno;
  143. }
  144. function result($query, $row = 0) {
  145. if(!$query || $query->num_rows == 0) {
  146. return null;
  147. }
  148. $query->data_seek($row);
  149. $assocs = $query->fetch_row();
  150. return $assocs[0];
  151. }
  152. function num_rows($query) {
  153. $query = $query ? $query->num_rows : 0;
  154. return $query;
  155. }
  156. function num_fields($query) {
  157. return $query ? $query->field_count : null;
  158. }
  159. function free_result($query) {
  160. return $query ? $query->free() : false;
  161. }
  162. function insert_id() {
  163. return ($id = $this->curlink->insert_id) >= 0 ? $id : $this->result($this->query('SELECT last_insert_id()'), 0);
  164. }
  165. function fetch_row($query) {
  166. $query = $query ? $query->fetch_row() : null;
  167. return $query;
  168. }
  169. function fetch_fields($query) {
  170. return $query ? $query->fetch_field() : null;
  171. }
  172. function version() {
  173. if(empty($this->version)) {
  174. $this->version = $this->curlink->server_info;
  175. }
  176. return $this->version;
  177. }
  178. function escape_string($str) {
  179. return $this->curlink->escape_string($str);
  180. }
  181. function close() {
  182. return $this->curlink->close();
  183. }
  184. function halt($message = '', $code = 0, $sql = '') {
  185. throw new DbException($message, $code, $sql);
  186. }
  187. function begin_transaction() {
  188. if(PHP_VERSION < '5.5') {
  189. return $this->curlink->autocommit(false);
  190. }
  191. return $this->curlink->begin_transaction();
  192. }
  193. function commit() {
  194. $cr = $this->curlink->commit();
  195. if(PHP_VERSION < '5.5') {
  196. $this->curlink->autocommit(true);
  197. }
  198. return $cr;
  199. }
  200. function rollback() {
  201. $rr = $this->curlink->rollback();
  202. if(PHP_VERSION < '5.5') {
  203. $this->curlink->autocommit(true);
  204. }
  205. return $rr;
  206. }
  207. }