| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- <?php
- // +----------------------------------------------------------------------
- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
- // +----------------------------------------------------------------------
- // | Author: liu21st <liu21st@gmail.com>
- // +----------------------------------------------------------------------
- defined('THINK_PATH') or exit();
- /**
- * PDO数据库驱动
- * @category Extend
- * @package Extend
- * @subpackage Driver.Db
- * @author liu21st <liu21st@gmail.com>
- */
- class DbPdo extends Db{
- protected $PDOStatement = null;
- private $table = '';
- /**
- * 架构函数 读取数据库配置信息
- * @access public
- * @param array $config 数据库配置数组
- */
- public function __construct($config=''){
- if ( !class_exists('PDO') ) {
- throw_exception(L('_NOT_SUPPERT_').':PDO');
- }
- if(!empty($config)) {
- $this->config = $config;
- if(empty($this->config['params'])) {
- $this->config['params'] = array();
- }
- }
- }
- /**
- * 连接数据库方法
- * @access public
- */
- public function connect($config='',$linkNum=0) {
- if ( !isset($this->linkID[$linkNum]) ) {
- if(empty($config)) $config = $this->config;
- if($this->pconnect) {
- $config['params'][PDO::ATTR_PERSISTENT] = true;
- }
- //$config['params'][PDO::ATTR_CASE] = C("DB_CASE_LOWER")?PDO::CASE_LOWER:PDO::CASE_UPPER;
- try{
- $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$config['params']);
- }catch (PDOException $e) {
- throw_exception($e->getMessage());
- }
- // 因为PDO的连接切换可能导致数据库类型不同,因此重新获取下当前的数据库类型
- $this->dbType = $this->_getDsnType($config['dsn']);
- if(in_array($this->dbType,array('MSSQL','ORACLE','IBASE','OCI'))) {
- // 由于PDO对于以上的数据库支持不够完美,所以屏蔽了 如果仍然希望使用PDO 可以注释下面一行代码
- throw_exception('由于目前PDO暂时不能完美支持'.$this->dbType.' 请使用官方的'.$this->dbType.'驱动');
- }
- $this->linkID[$linkNum]->exec('SET NAMES '.C('DB_CHARSET'));
- // 标记连接成功
- $this->connected = true;
- // 注销数据库连接配置信息
- if(1 != C('DB_DEPLOY_TYPE')) unset($this->config);
- }
- return $this->linkID[$linkNum];
- }
- /**
- * 释放查询结果
- * @access public
- */
- public function free() {
- $this->PDOStatement = null;
- }
- /**
- * 执行查询 返回数据集
- * @access public
- * @param string $str sql指令
- * @param array $bind 参数绑定
- * @return mixed
- */
- public function query($str,$bind=array()) {
- $this->initConnect(false);
- if ( !$this->_linkID ) return false;
- $this->queryStr = $str;
- if(!empty($bind)){
- $this->queryStr .= '[ '.print_r($bind,true).' ]';
- }
- //释放前次的查询结果
- if ( !empty($this->PDOStatement) ) $this->free();
- N('db_query',1);
- // 记录开始执行时间
- G('queryStartTime');
- $this->PDOStatement = $this->_linkID->prepare($str);
- if(false === $this->PDOStatement)
- throw_exception($this->error());
- $result = $this->PDOStatement->execute($bind);
- $this->debug();
- if ( false === $result ) {
- $this->error();
- return false;
- } else {
- return $this->getAll();
- }
- }
- /**
- * 执行语句
- * @access public
- * @param string $str sql指令
- * @param array $bind 参数绑定
- * @return integer
- */
- public function execute($str,$bind=array()) {
- $this->initConnect(true);
- if ( !$this->_linkID ) return false;
- $this->queryStr = $str;
- if(!empty($bind)){
- $this->queryStr .= '[ '.print_r($bind,true).' ]';
- }
- $flag = false;
- if($this->dbType == 'OCI')
- {
- if(preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $this->queryStr, $match)) {
- $this->table = C("DB_SEQUENCE_PREFIX").str_ireplace(C("DB_PREFIX"), "", $match[2]);
- $flag = (boolean)$this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'");
- }
- }//modify by wyfeng at 2009.08.28
- //释放前次的查询结果
- if ( !empty($this->PDOStatement) ) $this->free();
- N('db_write',1);
- // 记录开始执行时间
- G('queryStartTime');
- $this->PDOStatement = $this->_linkID->prepare($str);
- if(false === $this->PDOStatement) {
- throw_exception($this->error());
- }
- $result = $this->PDOStatement->execute($bind);
- $this->debug();
- if ( false === $result) {
- $this->error();
- return false;
- } else {
- $this->numRows = $this->PDOStatement->rowCount();
- if($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) {
- $this->lastInsID = $this->getLastInsertId();
- }
- return $this->numRows;
- }
- }
- /**
- * 启动事务
- * @access public
- * @return void
- */
- public function startTrans() {
- $this->initConnect(true);
- if ( !$this->_linkID ) return false;
- //数据rollback 支持
- if ($this->transTimes == 0) {
- $this->_linkID->beginTransaction();
- }
- $this->transTimes++;
- return ;
- }
- /**
- * 用于非自动提交状态下面的查询提交
- * @access public
- * @return boolen
- */
- public function commit() {
- if ($this->transTimes > 0) {
- $result = $this->_linkID->commit();
- $this->transTimes = 0;
- if(!$result){
- $this->error();
- return false;
- }
- }
- return true;
- }
- /**
- * 事务回滚
- * @access public
- * @return boolen
- */
- public function rollback() {
- if ($this->transTimes > 0) {
- $result = $this->_linkID->rollback();
- $this->transTimes = 0;
- if(!$result){
- $this->error();
- return false;
- }
- }
- return true;
- }
- /**
- * 获得所有的查询数据
- * @access private
- * @return array
- */
- private function getAll() {
- //返回数据集
- $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC);
- $this->numRows = count( $result );
- return $result;
- }
- /**
- * 取得数据表的字段信息
- * @access public
- */
- public function getFields($tableName) {
- $this->initConnect(true);
- if(C('DB_DESCRIBE_TABLE_SQL')) {
- // 定义特殊的字段查询SQL
- $sql = str_replace('%table%',$tableName,C('DB_DESCRIBE_TABLE_SQL'));
- }else{
- switch($this->dbType) {
- case 'MSSQL':
- case 'SQLSRV':
- $sql = "SELECT column_name as 'Name', data_type as 'Type', column_default as 'Default', is_nullable as 'Null'
- FROM information_schema.tables AS t
- JOIN information_schema.columns AS c
- ON t.table_catalog = c.table_catalog
- AND t.table_schema = c.table_schema
- AND t.table_name = c.table_name
- WHERE t.table_name = '$tableName'";
- break;
- case 'SQLITE':
- $sql = 'PRAGMA table_info ('.$tableName.') ';
- break;
- case 'ORACLE':
- case 'OCI':
- $sql = "SELECT a.column_name \"Name\",data_type \"Type\",decode(nullable,'Y',0,1) notnull,data_default \"Default\",decode(a.column_name,b.column_name,1,0) \"pk\" "
- ."FROM user_tab_columns a,(SELECT column_name FROM user_constraints c,user_cons_columns col "
- ."WHERE c.constraint_name=col.constraint_name AND c.constraint_type='P' and c.table_name='".strtoupper($tableName)
- ."') b where table_name='".strtoupper($tableName)."' and a.column_name=b.column_name(+)";
- break;
- case 'PGSQL':
- $sql = 'select fields_name as "Name",fields_type as "Type",fields_not_null as "Null",fields_key_name as "Key",fields_default as "Default",fields_default as "Extra" from table_msg('.$tableName.');';
- break;
- case 'IBASE':
- break;
- case 'MYSQL':
- default:
- $sql = 'DESCRIBE '.$tableName;//备注: 驱动类不只针对mysql,不能加``
- }
- }
- $result = $this->query($sql);
- $info = array();
- if($result) {
- foreach ($result as $key => $val) {
- $val = array_change_key_case($val);
- $val['name'] = isset($val['name'])?$val['name']:"";
- $val['type'] = isset($val['type'])?$val['type']:"";
- $name = isset($val['field'])?$val['field']:$val['name'];
- $info[$name] = array(
- 'name' => $name ,
- 'type' => $val['type'],
- 'notnull' => (bool)(((isset($val['null'])) && ($val['null'] === '')) || ((isset($val['notnull'])) && ($val['notnull'] === ''))), // not null is empty, null is yes
- 'default' => isset($val['default'])? $val['default'] :(isset($val['dflt_value'])?$val['dflt_value']:""),
- 'primary' => isset($val['key'])?strtolower($val['key']) == 'pri':(isset($val['pk'])?$val['pk']:false),
- 'autoinc' => isset($val['extra'])?strtolower($val['extra']) == 'auto_increment':(isset($val['key'])?$val['key']:false),
- );
- }
- }
- return $info;
- }
- /**
- * 取得数据库的表信息
- * @access public
- */
- public function getTables($dbName='') {
- if(C('DB_FETCH_TABLES_SQL')) {
- // 定义特殊的表查询SQL
- $sql = str_replace('%db%',$dbName,C('DB_FETCH_TABLES_SQL'));
- }else{
- switch($this->dbType) {
- case 'ORACLE':
- case 'OCI':
- $sql = 'SELECT table_name FROM user_tables';
- break;
- case 'MSSQL':
- case 'SQLSRV':
- $sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'";
- break;
- case 'PGSQL':
- $sql = "select tablename as Tables_in_test from pg_tables where schemaname ='public'";
- break;
- case 'IBASE':
- // 暂时不支持
- throw_exception(L('_NOT_SUPPORT_DB_').':IBASE');
- break;
- case 'SQLITE':
- $sql = "SELECT name FROM sqlite_master WHERE type='table' "
- . "UNION ALL SELECT name FROM sqlite_temp_master "
- . "WHERE type='table' ORDER BY name";
- break;
- case 'MYSQL':
- default:
- if(!empty($dbName)) {
- $sql = 'SHOW TABLES FROM '.$dbName;
- }else{
- $sql = 'SHOW TABLES ';
- }
- }
- }
- $result = $this->query($sql);
- $info = array();
- foreach ($result as $key => $val) {
- $info[$key] = current($val);
- }
- return $info;
- }
- /**
- * limit分析
- * @access protected
- * @param mixed $lmit
- * @return string
- */
- protected function parseLimit($limit) {
- $limitStr = '';
- if(!empty($limit)) {
- switch($this->dbType){
- case 'PGSQL':
- case 'SQLITE':
- $limit = explode(',',$limit);
- if(count($limit)>1) {
- $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' ';
- }else{
- $limitStr .= ' LIMIT '.$limit[0].' ';
- }
- break;
- case 'MSSQL':
- case 'SQLSRV':
- break;
- case 'IBASE':
- // 暂时不支持
- break;
- case 'ORACLE':
- case 'OCI':
- break;
- case 'MYSQL':
- default:
- $limitStr .= ' LIMIT '.$limit.' ';
- }
- }
- return $limitStr;
- }
- /**
- * 字段和表名处理
- * @access protected
- * @param string $key
- * @return string
- */
- protected function parseKey(&$key) {
- if($this->dbType=='MYSQL'){
- $key = trim($key);
- if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
- $key = '`'.$key.'`';
- }
- return $key;
- }else{
- return parent::parseKey($key);
- }
- }
- /**
- * 关闭数据库
- * @access public
- */
- public function close() {
- $this->_linkID = null;
- }
- /**
- * 数据库错误信息
- * 并显示当前的SQL语句
- * @access public
- * @return string
- */
- public function error() {
- if($this->PDOStatement) {
- $error = $this->PDOStatement->errorInfo();
- $this->error = $error[1].':'.$error[2];
- }else{
- $this->error = '';
- }
- if('' != $this->queryStr){
- $this->error .= "\n [ SQL语句 ] : ".$this->queryStr;
- }
- trace($this->error,'','ERR');
- return $this->error;
- }
- /**
- * SQL指令安全过滤
- * @access public
- * @param string $str SQL指令
- * @return string
- */
- public function escapeString($str) {
- switch($this->dbType) {
- case 'PGSQL':
- case 'MSSQL':
- case 'SQLSRV':
- case 'MYSQL':
- return addslashes($str);
- case 'IBASE':
- case 'SQLITE':
- case 'ORACLE':
- case 'OCI':
- return str_ireplace("'", "''", $str);
- }
- }
- /**
- * value分析
- * @access protected
- * @param mixed $value
- * @return string
- */
- protected function parseValue($value) {
- if(is_string($value)) {
- $value = strpos($value,':') === 0 ? $this->escapeString($value) : '\''.$this->escapeString($value).'\'';
- }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
- $value = $this->escapeString($value[1]);
- }elseif(is_array($value)) {
- $value = array_map(array($this, 'parseValue'),$value);
- }elseif(is_bool($value)){
- $value = $value ? '1' : '0';
- }elseif(is_null($value)){
- $value = 'null';
- }
- return $value;
- }
- /**
- * 获取最后插入id
- * @access public
- * @return integer
- */
- public function getLastInsertId() {
- switch($this->dbType) {
- case 'PGSQL':
- case 'SQLITE':
- case 'MSSQL':
- case 'SQLSRV':
- case 'IBASE':
- case 'MYSQL':
- return $this->_linkID->lastInsertId();
- case 'ORACLE':
- case 'OCI':
- $sequenceName = $this->table;
- $vo = $this->query("SELECT {$sequenceName}.currval currval FROM dual");
- return $vo?$vo[0]["currval"]:0;
- }
- }
- }
|