diff --git a/Library/Think/Db/Driver/Mysql.php b/Library/Think/Db/Driver/Mysql.php index 150faf09..efa6dc4d 100644 --- a/Library/Think/Db/Driver/Mysql.php +++ b/Library/Think/Db/Driver/Mysql.php @@ -1,75 +1,91 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * mysql数据库驱动 - * @category Extend - * @package Extend - * @subpackage Driver.Db - * @author liu21st - */ -class Mysql extends Driver{ - /** - * 取得数据表的字段信息 - * @access public - */ - public function getFields($tableName) { - $this->initConnect(true); - $sql = 'SHOW COLUMNS FROM `'.$tableName.'`'; - $result = $this->query($sql); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - */ - public function getTables($dbName='') { - $sql = !empty($dbName)?'SHOW TABLES FROM '.$dbName:'SHOW TABLES '; - $result = $this->query($sql); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * 字段和表名处理 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey(&$key) { - $key = trim($key); - if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { - $key = '`'.$key.'`'; - } - return $key; - } - -} + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * mysql数据库驱动 + */ +class Mysql extends Driver{ + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'mysql:dbname='.$config['database'].';host='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ';port='.$config['hostport']; + }elseif(!empty($config['socket'])){ + $dsn .= ';unix_socket='.$config['socket']; + } + if(!empty($config['charset'])){ + $dsn .= ';charset='.$config['charset']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + */ + public function getFields($tableName) { + $this->initConnect(true); + $sql = 'SHOW COLUMNS FROM `'.$tableName.'`'; + $result = $this->query($sql); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['key']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + */ + public function getTables($dbName='') { + $sql = !empty($dbName)?'SHOW TABLES FROM '.$dbName:'SHOW TABLES '; + $result = $this->query($sql); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * 字段和表名处理 + * @access protected + * @param string $key + * @return string + */ + protected function parseKey(&$key) { + $key = trim($key); + if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) { + $key = '`'.$key.'`'; + } + return $key; + } + +} diff --git a/Library/Think/Db/Driver/Oracle.php b/Library/Think/Db/Driver/Oracle.php index 16705f60..6043e0d2 100644 --- a/Library/Think/Db/Driver/Oracle.php +++ b/Library/Think/Db/Driver/Oracle.php @@ -1,172 +1,182 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Oracle数据库驱动 - * @category Extend - * @package Extend - * @subpackage Driver.Db - * @author ZhangXuehun - */ -class Oracle extends Driver{ - - private $table = ''; - protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%'; - - /** - * 执行语句 - * @access public - * @param string $str sql指令 - * @return integer - */ - public function execute($str,$bind=[]) { - $this->initConnect(true); - if ( !$this->_linkID ) return false; - $this->queryStr = $str; - $flag = false; - 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) . "'"); - } - //释放前次的查询结果 - if ( !empty($this->PDOStatement) ) $this->free(); - $this->executeTimes++; - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->_linkID->prepare($str); - if(false === $this->PDOStatement) { - E($this->error()); - } - $result = $this->PDOStatement->execute($bind); - $this->debug(false); - 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 - */ - public function getFields($tableName) { - $result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_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(+)"); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[strtolower($val['column_name'])] = [ - 'name' => strtolower($val['column_name']), - 'type' => strtolower($val['data_type']), - 'notnull' => $val['notnull'], - 'default' => $val['data_default'], - 'primary' => $val['pk'], - 'autoinc' => $val['pk'], - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息(暂时实现取得用户表信息) - * @access public - */ - public function getTables($dbName='') { - $result = $this->query("select table_name from user_tables"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL指令 - * @return string - */ - public function escapeString($str) { - return str_ireplace("'", "''", $str); - } - - /** - * 获取最后插入id ,仅适用于采用序列+触发器结合生成ID的方式 - * 在config.php中指定 - * 'DB_TRIGGER_PREFIX' => 'tr_', - * 'DB_SEQUENCE_PREFIX' => 'ts_', - * eg:表 tb_user - * 相对tb_user的序列为: - * -- Create sequence - * create sequence TS_USER - * minvalue 1 - * maxvalue 999999999999999999999999999 - * start with 1 - * increment by 1 - * nocache; - * 相对tb_user,ts_user的触发器为: - * create or replace trigger TR_USER - * before insert on "TB_USER" - * for each row - * begin - * select "TS_USER".nextval into :NEW.ID from dual; - * end; - * @access public - * @return integer - */ - public function getLastInsertId() { - if(empty($this->table)) { - return 0; - } - $sequenceName = $this->table; - $vo = $this->query("SELECT {$sequenceName}.currval currval FROM dual"); - return $vo?$vo[0]["currval"]:0; - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) - $limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")"; - else - $limitStr = "(numrow>0 AND numrow<=".$limit[0].")"; - } - return $limitStr?' WHERE '.$limitStr:''; - } - - /** - * 设置锁机制 - * @access protected - * @return string - */ - protected function parseLock($lock=false) { - if(!$lock) return ''; - return ' FOR UPDATE NOWAIT '; - } -} + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Oracle数据库驱动 + */ +class Oracle extends Driver{ + + private $table = ''; + protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%'; + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'oci:dbname='.$config['database']; + if(!empty($config['charset'])) { + $dsn .= ';charset='.$config['charset']; + } + return $dsn; + } + + /** + * 执行语句 + * @access public + * @param string $str sql指令 + * @return integer + */ + public function execute($str,$bind=[]) { + $this->initConnect(true); + if ( !$this->_linkID ) return false; + $this->queryStr = $str; + $flag = false; + 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) . "'"); + } + //释放前次的查询结果 + if ( !empty($this->PDOStatement) ) $this->free(); + $this->executeTimes++; + // 记录开始执行时间 + $this->debug(true); + $this->PDOStatement = $this->_linkID->prepare($str); + if(false === $this->PDOStatement) { + E($this->error()); + } + $result = $this->PDOStatement->execute($bind); + $this->debug(false); + 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 + */ + public function getFields($tableName) { + $result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_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(+)"); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[strtolower($val['column_name'])] = [ + 'name' => strtolower($val['column_name']), + 'type' => strtolower($val['data_type']), + 'notnull' => $val['notnull'], + 'default' => $val['data_default'], + 'primary' => $val['pk'], + 'autoinc' => $val['pk'], + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息(暂时实现取得用户表信息) + * @access public + */ + public function getTables($dbName='') { + $result = $this->query("select table_name from user_tables"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL指令 + * @return string + */ + public function escapeString($str) { + return str_ireplace("'", "''", $str); + } + + /** + * 获取最后插入id ,仅适用于采用序列+触发器结合生成ID的方式 + * 在config.php中指定 + * 'DB_TRIGGER_PREFIX' => 'tr_', + * 'DB_SEQUENCE_PREFIX' => 'ts_', + * eg:表 tb_user + * 相对tb_user的序列为: + * -- Create sequence + * create sequence TS_USER + * minvalue 1 + * maxvalue 999999999999999999999999999 + * start with 1 + * increment by 1 + * nocache; + * 相对tb_user,ts_user的触发器为: + * create or replace trigger TR_USER + * before insert on "TB_USER" + * for each row + * begin + * select "TS_USER".nextval into :NEW.ID from dual; + * end; + * @access public + * @return integer + */ + public function getLastInsertId() { + if(empty($this->table)) { + return 0; + } + $sequenceName = $this->table; + $vo = $this->query("SELECT {$sequenceName}.currval currval FROM dual"); + return $vo?$vo[0]["currval"]:0; + } + + /** + * limit + * @access public + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) + $limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0]+$limit[1]) . ")"; + else + $limitStr = "(numrow>0 AND numrow<=".$limit[0].")"; + } + return $limitStr?' WHERE '.$limitStr:''; + } + + /** + * 设置锁机制 + * @access protected + * @return string + */ + protected function parseLock($lock=false) { + if(!$lock) return ''; + return ' FOR UPDATE NOWAIT '; + } +} diff --git a/Library/Think/Db/Driver/Pgsql.php b/Library/Think/Db/Driver/Pgsql.php index 6bffc13e..8dd72cac 100644 --- a/Library/Think/Db/Driver/Pgsql.php +++ b/Library/Think/Db/Driver/Pgsql.php @@ -1,80 +1,90 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Pgsql数据库驱动 - * @category Extend - * @package Extend - * @subpackage Driver.Db - * @author liu21st - */ -class Pgsql extends Driver{ - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - $result = $this->query('select fields_name as "field",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.');'); - $info = []; - if($result){ - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * limit分析 - * @access protected - * @param mixed $lmit - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) { - $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; - }else{ - $limitStr .= ' LIMIT '.$limit[0].' '; - } - } - return $limitStr; - } - -} + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Pgsql数据库驱动 + */ +class Pgsql extends Driver{ + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'pgsql:dbname='.$config['database'].';host='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ';port='.$config['hostport']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + $result = $this->query('select fields_name as "field",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.');'); + $info = []; + if($result){ + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['key']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * limit分析 + * @access protected + * @param mixed $lmit + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) { + $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; + }else{ + $limitStr .= ' LIMIT '.$limit[0].' '; + } + } + return $limitStr; + } + +} diff --git a/Library/Think/Db/Driver/Sqlite.php b/Library/Think/Db/Driver/Sqlite.php index f1f1899c..fcb77e13 100644 --- a/Library/Think/Db/Driver/Sqlite.php +++ b/Library/Think/Db/Driver/Sqlite.php @@ -1,90 +1,97 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Sqlite数据库驱动 - * @category Extend - * @package Extend - * @subpackage Driver.Db - * @author liu21st - */ -class Sqlite extends Driver { - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - $result = $this->query('PRAGMA table_info( '.$tableName.' )'); - $info = []; - if($result){ - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['dey']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("SELECT name FROM sqlite_master WHERE type='table' " - . "UNION ALL SELECT name FROM sqlite_temp_master " - . "WHERE type='table' ORDER BY name"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL指令 - * @return string - */ - public function escapeString($str) { - return str_ireplace("'", "''", $str); - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) { - $limitStr = ''; - if(!empty($limit)) { - $limit = explode(',',$limit); - if(count($limit)>1) { - $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; - }else{ - $limitStr .= ' LIMIT '.$limit[0].' '; - } - } - return $limitStr; - } -} + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Sqlite数据库驱动 + */ +class Sqlite extends Driver { + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'sqlite:'.$config['database']; + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + $result = $this->query('PRAGMA table_info( '.$tableName.' )'); + $info = []; + if($result){ + foreach ($result as $key => $val) { + $info[$val['field']] = [ + 'name' => $val['field'], + 'type' => $val['type'], + 'notnull' => (bool) ($val['null'] === ''), // not null is empty, null is yes + 'default' => $val['default'], + 'primary' => (strtolower($val['dey']) == 'pri'), + 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), + ]; + } + } + return $info; + } + + /** + * 取得数据库的表信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("SELECT name FROM sqlite_master WHERE type='table' " + . "UNION ALL SELECT name FROM sqlite_temp_master " + . "WHERE type='table' ORDER BY name"); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * SQL指令安全过滤 + * @access public + * @param string $str SQL指令 + * @return string + */ + public function escapeString($str) { + return str_ireplace("'", "''", $str); + } + + /** + * limit + * @access public + * @return string + */ + public function parseLimit($limit) { + $limitStr = ''; + if(!empty($limit)) { + $limit = explode(',',$limit); + if(count($limit)>1) { + $limitStr .= ' LIMIT '.$limit[1].' OFFSET '.$limit[0].' '; + }else{ + $limitStr .= ' LIMIT '.$limit[0].' '; + } + } + return $limitStr; + } +} diff --git a/Library/Think/Db/Driver/Sqlsrv.php b/Library/Think/Db/Driver/Sqlsrv.php index ec7c4da4..ee95b777 100644 --- a/Library/Think/Db/Driver/Sqlsrv.php +++ b/Library/Think/Db/Driver/Sqlsrv.php @@ -1,131 +1,148 @@ - -// +---------------------------------------------------------------------- - -namespace Think\Db\Driver; -use Think\Db\Driver; - -/** - * Sqlsrv数据库驱动 - * @category Extend - * @package Extend - * @subpackage Driver.Db - * @author liu21st - */ -class Sqlsrv extends Driver{ - protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) { - $result = $this->query("SELECT column_name, data_type, column_default, is_nullable - 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'"); - $info = []; - if($result) { - foreach ($result as $key => $val) { - $info[$val['column_name']] = [ - 'name' => $val['column_name'], - 'type' => $val['data_type'], - 'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes - 'default' => $val['column_default'], - 'primary' => false, - 'autoinc' => false, - ]; - } - } - return $info; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getTables($dbName='') { - $result = $this->query("SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_TYPE = 'BASE TABLE' - "); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return string - */ - protected function parseOrder($order) { - return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()'; - } - - /** - * limit - * @access public - * @param mixed $limit - * @return string - */ - public function parseLimit($limit) { - if(empty($limit)) return ''; - $limit = explode(',',$limit); - if(count($limit)>1) - $limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')'; - else - $limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")"; - return 'WHERE '.$limitStr; - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return false | integer - */ - public function update($data,$options) { - $this->model = $options['model']; - $sql = 'UPDATE ' - .$this->parseTable($options['table']) - .$this->parseSet($data) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql); - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options=[]) { - $this->model = $options['model']; - $sql = 'DELETE FROM ' - .$this->parseTable($options['table']) - .$this->parseWhere(!empty($options['where'])?$options['where']:'') - .$this->parseLock(isset($options['lock'])?$options['lock']:false) - .$this->parseComment(!empty($options['comment'])?$options['comment']:''); - return $this->execute($sql); - } - -} + +// +---------------------------------------------------------------------- + +namespace Think\Db\Driver; +use Think\Db\Driver; + +/** + * Sqlsrv数据库驱动 + */ +class Sqlsrv extends Driver{ + protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; + // PDO连接参数 + protected $options = [ + PDO::ATTR_CASE => PDO::CASE_LOWER, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, + ]; + + /** + * 解析pdo连接的dsn信息 + * @access public + * @param array $config 连接信息 + * @return string + */ + protected function parseDsn($config){ + $dsn = 'sqlsrv:dbname='.$config['database'].';Server='.$config['hostname']; + if(!empty($config['hostport'])) { + $dsn .= ','.$config['hostport']; + } + return $dsn; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getFields($tableName) { + $result = $this->query("SELECT column_name, data_type, column_default, is_nullable + 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'"); + $info = []; + if($result) { + foreach ($result as $key => $val) { + $info[$val['column_name']] = [ + 'name' => $val['column_name'], + 'type' => $val['data_type'], + 'notnull' => (bool) ($val['is_nullable'] === ''), // not null is empty, null is yes + 'default' => $val['column_default'], + 'primary' => false, + 'autoinc' => false, + ]; + } + } + return $info; + } + + /** + * 取得数据表的字段信息 + * @access public + * @return array + */ + public function getTables($dbName='') { + $result = $this->query("SELECT TABLE_NAME + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_TYPE = 'BASE TABLE' + "); + $info = []; + foreach ($result as $key => $val) { + $info[$key] = current($val); + } + return $info; + } + + /** + * order分析 + * @access protected + * @param mixed $order + * @return string + */ + protected function parseOrder($order) { + return !empty($order)? ' ORDER BY '.$order:' ORDER BY rand()'; + } + + /** + * limit + * @access public + * @param mixed $limit + * @return string + */ + public function parseLimit($limit) { + if(empty($limit)) return ''; + $limit = explode(',',$limit); + if(count($limit)>1) + $limitStr = '(T1.ROW_NUMBER BETWEEN '.$limit[0].' + 1 AND '.$limit[0].' + '.$limit[1].')'; + else + $limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND '.$limit[0].")"; + return 'WHERE '.$limitStr; + } + + /** + * 更新记录 + * @access public + * @param mixed $data 数据 + * @param array $options 表达式 + * @return false | integer + */ + public function update($data,$options) { + $this->model = $options['model']; + $sql = 'UPDATE ' + .$this->parseTable($options['table']) + .$this->parseSet($data) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + + /** + * 删除记录 + * @access public + * @param array $options 表达式 + * @return false | integer + */ + public function delete($options=[]) { + $this->model = $options['model']; + $sql = 'DELETE FROM ' + .$this->parseTable($options['table']) + .$this->parseWhere(!empty($options['where'])?$options['where']:'') + .$this->parseLock(isset($options['lock'])?$options['lock']:false) + .$this->parseComment(!empty($options['comment'])?$options['comment']:''); + return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:[])); + } + +}