db_driver_pdo.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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_pdo extends db_driver_mysqli {
  11. var $tablepre;
  12. var $version = '';
  13. var $drivertype = 'pdo';
  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 connect($serverid = 1) {
  27. if(empty($this->config) || empty($this->config[$serverid])) {
  28. $this->halt('config_db_not_found');
  29. }
  30. if(!empty($this->config[$serverid]['dsn'])) {
  31. $this->link[$serverid] = $this->_dbconnectWithDSN(
  32. $this->config[$serverid]['dsn'],
  33. $this->config[$serverid]['dbuser'],
  34. $this->config[$serverid]['dbpw'],
  35. $this->config[$serverid]['pconnect']
  36. );
  37. } else {
  38. $this->link[$serverid] = $this->_dbconnect(
  39. $this->config[$serverid]['dbhost'],
  40. $this->config[$serverid]['dbuser'],
  41. $this->config[$serverid]['dbpw'],
  42. $this->config[$serverid]['dbcharset'],
  43. $this->config[$serverid]['dbname'],
  44. $this->config[$serverid]['pconnect']
  45. );
  46. }
  47. $this->curlink = $this->link[$serverid];
  48. }
  49. function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect, $halt = true) {
  50. $option = [];
  51. if(intval($pconnect) === 1) {
  52. $option = [PDO::ATTR_PERSISTENT => true];
  53. }
  54. $link = new PDO('mysql:host='.$dbhost.';dbname='.$dbname.';charset='.$dbcharset, $dbuser, $dbpw, $option);
  55. if(!$link) {
  56. $halt && $this->halt('notconnect', $this->errno());
  57. } else {
  58. $this->curlink = $link;
  59. $link->query('SET sql_mode=\'\',character_set_client=binary');
  60. }
  61. return $link;
  62. }
  63. function _dbconnectWithDSN($dsn, $dbuser, $dbpw, $pconnect, $halt = true) {
  64. $option = [];
  65. if(intval($pconnect) === 1) {
  66. $option = [PDO::ATTR_PERSISTENT => true];
  67. }
  68. $link = new PDO($dsn, $dbuser, $dbpw, $option);
  69. if(!$link) {
  70. $halt && $this->halt('notconnect', $this->errno());
  71. } else {
  72. $this->curlink = $link;
  73. $link->query('SET sql_mode=\'\',character_set_client=binary');
  74. }
  75. return $link;
  76. }
  77. function select_db($dbname) {
  78. return false;
  79. }
  80. function fetch_array($query, $result_type = MYSQLI_ASSOC) {
  81. $result_type = match ($result_type) {
  82. 'MYSQL_ASSOC', MYSQLI_ASSOC, 1 => PDO::FETCH_ASSOC,
  83. 'MYSQL_NUM', MYSQLI_NUM, 2 => PDO::FETCH_NUM,
  84. default => PDO::FETCH_BOTH,
  85. };
  86. return $query ? $query->fetch($result_type) : null;
  87. }
  88. function fetch_first($sql) {
  89. return $this->fetch_array($this->query($sql));
  90. }
  91. function result_first($sql) {
  92. return $this->result($this->query($sql), 0);
  93. }
  94. public function query($sql, $silent = false, $unbuffered = false) {
  95. $arg = [];
  96. if(is_array($sql)) {
  97. $arg = !empty($sql[1]) ? (array)$sql[1] : [];
  98. $sql = $sql[0];
  99. }
  100. if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  101. $starttime = microtime(true);
  102. }
  103. if('UNBUFFERED' === $silent) {
  104. $silent = false;
  105. $unbuffered = true;
  106. } elseif('SILENT' === $silent) {
  107. $silent = true;
  108. $unbuffered = false;
  109. }
  110. if(!$unbuffered) {
  111. $this->curlink->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, TRUE);
  112. }
  113. $query = $this->curlink->prepare($sql);
  114. try {
  115. $query->execute($arg);
  116. } catch (Exception $e) {
  117. if(in_array($this->errno(), ['01002', '08003', '08S01', '08007']) && !str_starts_with($silent, 'RETRY')) {
  118. $this->connect();
  119. return $this->query([$sql, $arg], 'RETRY'.$silent);
  120. }
  121. if(!$silent) {
  122. $this->halt($this->error(), $this->errno(), $sql);
  123. }
  124. }
  125. if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  126. $this->sqldebug[] = [$sql, number_format((microtime(true) - $starttime), 6), debug_backtrace(), $this->curlink, $arg];
  127. }
  128. $this->querynum++;
  129. $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
  130. if($cmd === 'UPDATE' || $cmd === 'DELETE' || $cmd === 'INSERT') {
  131. $this->rowCount = $query->rowCount();
  132. }
  133. return $query;
  134. }
  135. function affected_rows() {
  136. return $this->rowCount;
  137. }
  138. function error() {
  139. return (($this->curlink) ? $this->curlink->errorInfo()[2] : 'pdo_error');
  140. }
  141. function errno() {
  142. return intval(($this->curlink) ? $this->curlink->errorCode() : 99999);
  143. }
  144. function result($query, $row = 0) {
  145. if(!$query || $query->rowCount() == 0) {
  146. return null;
  147. }
  148. return $query->fetchColumn($row);
  149. }
  150. function num_rows($query) {
  151. return $query ? $query->rowCount() : 0;
  152. }
  153. function num_fields($query) {
  154. return $query ? $query->columnCount() : null;
  155. }
  156. function free_result($query) {
  157. return true;
  158. }
  159. function insert_id() {
  160. return ($id = $this->curlink->lastInsertId()) >= 0 ? $id : $this->result($this->query('SELECT last_insert_id()'), 0);
  161. }
  162. function fetch_row($query) {
  163. return $query ? $query->fetch_row() : null;
  164. }
  165. function fetch_fields($query) {
  166. return $query ? $query->fetch_field() : null;
  167. }
  168. function version() {
  169. if(empty($this->version)) {
  170. $this->version = $this->curlink->getAttribute(PDO::ATTR_SERVER_VERSION);
  171. }
  172. return $this->version;
  173. }
  174. function escape_string($str) {
  175. return substr($this->curlink->quote($str), 1, -1);
  176. }
  177. function close() {
  178. return true;
  179. }
  180. function halt($message = '', $code = 0, $sql = '') {
  181. throw new DbException(var_export($message, true), $code, $sql);
  182. }
  183. function begin_transaction() {
  184. if($this->curlink->beginTransaction()) {
  185. return true;
  186. } else {
  187. return false;
  188. }
  189. }
  190. function commit() {
  191. if($this->curlink->commit()) {
  192. return true;
  193. } else {
  194. return false;
  195. }
  196. }
  197. function rollback() {
  198. if($this->curlink->rollBack()) {
  199. return true;
  200. } else {
  201. return false;
  202. }
  203. }
  204. }