DbMysql.class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. defined('THINK_PATH') or exit();
  12. /**
  13. * Mysql数据库驱动类
  14. * @category Think
  15. * @package Think
  16. * @subpackage Driver.Db
  17. * @author liu21st <liu21st@gmail.com>
  18. */
  19. class DbMysql extends Db{
  20. /**
  21. * 架构函数 读取数据库配置信息
  22. * @access public
  23. * @param array $config 数据库配置数组
  24. */
  25. public function __construct($config=''){
  26. if ( !extension_loaded('mysql') ) {
  27. throw_exception(L('_NOT_SUPPERT_').':mysql');
  28. }
  29. if(!empty($config)) {
  30. $this->config = $config;
  31. if(empty($this->config['params'])) {
  32. $this->config['params'] = '';
  33. }
  34. }
  35. }
  36. /**
  37. * 连接数据库方法
  38. * @access public
  39. * @throws ThinkExecption
  40. */
  41. public function connect($config='',$linkNum=0,$force=false) {
  42. if ( !isset($this->linkID[$linkNum]) ) {
  43. if(empty($config)) $config = $this->config;
  44. // 处理不带端口号的socket连接情况
  45. $host = $config['hostname'].($config['hostport']?":{$config['hostport']}":'');
  46. // 是否长连接
  47. $pconnect = !empty($config['params']['persist'])? $config['params']['persist']:$this->pconnect;
  48. if($pconnect) {
  49. $this->linkID[$linkNum] = mysql_pconnect( $host, $config['username'], $config['password'],131072);
  50. }else{
  51. $this->linkID[$linkNum] = mysql_connect( $host, $config['username'], $config['password'],true,131072);
  52. }
  53. if ( !$this->linkID[$linkNum] || (!empty($config['database']) && !mysql_select_db($config['database'], $this->linkID[$linkNum])) ) {
  54. throw_exception(mysql_error());
  55. }
  56. $dbVersion = mysql_get_server_info($this->linkID[$linkNum]);
  57. //使用UTF8存取数据库
  58. mysql_query("SET NAMES '".C('DB_CHARSET')."'", $this->linkID[$linkNum]);
  59. //设置 sql_model
  60. if($dbVersion >'5.0.1'){
  61. mysql_query("SET sql_mode=''",$this->linkID[$linkNum]);
  62. }
  63. // 标记连接成功
  64. $this->connected = true;
  65. // 注销数据库连接配置信息
  66. if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
  67. }
  68. return $this->linkID[$linkNum];
  69. }
  70. /**
  71. * 释放查询结果
  72. * @access public
  73. */
  74. public function free() {
  75. mysql_free_result($this->queryID);
  76. $this->queryID = null;
  77. }
  78. /**
  79. * 执行查询 返回数据集
  80. * @access public
  81. * @param string $str sql指令
  82. * @return mixed
  83. */
  84. public function query($str) {
  85. if(0===stripos($str, 'call')){ // 存储过程查询支持
  86. $this->close();
  87. $this->connected = false;
  88. }
  89. $this->initConnect(false);
  90. if ( !$this->_linkID ) return false;
  91. $this->queryStr = $str;
  92. //释放前次的查询结果
  93. if ( $this->queryID ) { $this->free(); }
  94. N('db_query',1);
  95. // 记录开始执行时间
  96. G('queryStartTime');
  97. $this->queryID = mysql_query($str, $this->_linkID);
  98. $this->debug();
  99. if ( false === $this->queryID ) {
  100. $this->error();
  101. return false;
  102. } else {
  103. $this->numRows = mysql_num_rows($this->queryID);
  104. return $this->getAll();
  105. }
  106. }
  107. /**
  108. * 执行语句
  109. * @access public
  110. * @param string $str sql指令
  111. * @return integer|false
  112. */
  113. public function execute($str) {
  114. $this->initConnect(true);
  115. if ( !$this->_linkID ) return false;
  116. $this->queryStr = $str;
  117. //释放前次的查询结果
  118. if ( $this->queryID ) { $this->free(); }
  119. N('db_write',1);
  120. // 记录开始执行时间
  121. G('queryStartTime');
  122. $result = mysql_query($str, $this->_linkID) ;
  123. $this->debug();
  124. if ( false === $result) {
  125. $this->error();
  126. return false;
  127. } else {
  128. $this->numRows = mysql_affected_rows($this->_linkID);
  129. $this->lastInsID = mysql_insert_id($this->_linkID);
  130. return $this->numRows;
  131. }
  132. }
  133. /**
  134. * 启动事务
  135. * @access public
  136. * @return void
  137. */
  138. public function startTrans() {
  139. $this->initConnect(true);
  140. if ( !$this->_linkID ) return false;
  141. //数据rollback 支持
  142. if ($this->transTimes == 0) {
  143. mysql_query('START TRANSACTION', $this->_linkID);
  144. }
  145. $this->transTimes++;
  146. return ;
  147. }
  148. /**
  149. * 用于非自动提交状态下面的查询提交
  150. * @access public
  151. * @return boolen
  152. */
  153. public function commit() {
  154. if ($this->transTimes > 0) {
  155. $result = mysql_query('COMMIT', $this->_linkID);
  156. $this->transTimes = 0;
  157. if(!$result){
  158. $this->error();
  159. return false;
  160. }
  161. }
  162. return true;
  163. }
  164. /**
  165. * 事务回滚
  166. * @access public
  167. * @return boolen
  168. */
  169. public function rollback() {
  170. if ($this->transTimes > 0) {
  171. $result = mysql_query('ROLLBACK', $this->_linkID);
  172. $this->transTimes = 0;
  173. if(!$result){
  174. $this->error();
  175. return false;
  176. }
  177. }
  178. return true;
  179. }
  180. /**
  181. * 获得所有的查询数据
  182. * @access private
  183. * @return array
  184. */
  185. private function getAll() {
  186. //返回数据集
  187. $result = array();
  188. if($this->numRows >0) {
  189. while($row = mysql_fetch_assoc($this->queryID)){
  190. $result[] = $row;
  191. }
  192. mysql_data_seek($this->queryID,0);
  193. }
  194. return $result;
  195. }
  196. /**
  197. * 取得数据表的字段信息
  198. * @access public
  199. * @return array
  200. */
  201. public function getFields($tableName) {
  202. $result = $this->query('SHOW COLUMNS FROM '.$this->parseKey($tableName));
  203. $info = array();
  204. if($result) {
  205. foreach ($result as $key => $val) {
  206. $info[$val['Field']] = array(
  207. 'name' => $val['Field'],
  208. 'type' => $val['Type'],
  209. 'notnull' => (bool) (strtoupper($val['Null']) === 'NO'), // not null is empty, null is yes
  210. 'default' => $val['Default'],
  211. 'primary' => (strtolower($val['Key']) == 'pri'),
  212. 'autoinc' => (strtolower($val['Extra']) == 'auto_increment'),
  213. );
  214. }
  215. }
  216. return $info;
  217. }
  218. /**
  219. * 取得数据库的表信息
  220. * @access public
  221. * @return array
  222. */
  223. public function getTables($dbName='') {
  224. if(!empty($dbName)) {
  225. $sql = 'SHOW TABLES FROM '.$dbName;
  226. }else{
  227. $sql = 'SHOW TABLES ';
  228. }
  229. $result = $this->query($sql);
  230. $info = array();
  231. foreach ($result as $key => $val) {
  232. $info[$key] = current($val);
  233. }
  234. return $info;
  235. }
  236. /**
  237. * 替换记录
  238. * @access public
  239. * @param mixed $data 数据
  240. * @param array $options 参数表达式
  241. * @return false | integer
  242. */
  243. public function replace($data,$options=array()) {
  244. foreach ($data as $key=>$val){
  245. $value = $this->parseValue($val);
  246. if(is_scalar($value)) { // 过滤非标量数据
  247. $values[] = $value;
  248. $fields[] = $this->parseKey($key);
  249. }
  250. }
  251. $sql = 'REPLACE INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')';
  252. return $this->execute($sql);
  253. }
  254. /**
  255. * 插入记录
  256. * @access public
  257. * @param mixed $datas 数据
  258. * @param array $options 参数表达式
  259. * @param boolean $replace 是否replace
  260. * @return false | integer
  261. */
  262. public function insertAll($datas,$options=array(),$replace=false) {
  263. if(!is_array($datas[0])) return false;
  264. $fields = array_keys($datas[0]);
  265. array_walk($fields, array($this, 'parseKey'));
  266. $values = array();
  267. foreach ($datas as $data){
  268. $value = array();
  269. foreach ($data as $key=>$val){
  270. $val = $this->parseValue($val);
  271. if(is_scalar($val)) { // 过滤非标量数据
  272. $value[] = $val;
  273. }
  274. }
  275. $values[] = '('.implode(',', $value).')';
  276. }
  277. $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES '.implode(',',$values);
  278. return $this->execute($sql);
  279. }
  280. /**
  281. * 关闭数据库
  282. * @access public
  283. * @return void
  284. */
  285. public function close() {
  286. if ($this->_linkID){
  287. mysql_close($this->_linkID);
  288. }
  289. $this->_linkID = null;
  290. }
  291. /**
  292. * 数据库错误信息
  293. * 并显示当前的SQL语句
  294. * @access public
  295. * @return string
  296. */
  297. public function error() {
  298. $this->error = mysql_errno().':'.mysql_error($this->_linkID);
  299. if('' != $this->queryStr){
  300. $this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
  301. }
  302. trace($this->error,'','ERR');
  303. return $this->error;
  304. }
  305. /**
  306. * SQL指令安全过滤
  307. * @access public
  308. * @param string $str SQL字符串
  309. * @return string
  310. */
  311. public function escapeString($str) {
  312. if($this->_linkID) {
  313. return mysql_real_escape_string($str,$this->_linkID);
  314. }else{
  315. return mysql_escape_string($str);
  316. }
  317. }
  318. /**
  319. * 字段和表名处理添加`
  320. * @access protected
  321. * @param string $key
  322. * @return string
  323. */
  324. protected function parseKey(&$key) {
  325. $key = trim($key);
  326. if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
  327. $key = '`'.$key.'`';
  328. }
  329. return $key;
  330. }
  331. }