DbMysql.class.php 15 KB

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