<?php
/*
 * puyuetianPHP轻框架 核心函数
 * 作者：蒲乐天（puyuetian）
 * QQ：632827168
 * 官网：http://www.puyuetian.com
 *
 * 作者允许您转载和使用，但必须注明来自puyuetianPHP轻框架。
 */
/********************************************
数据库操作类 - 获取、修改、添加、删除表信息，必须为id为唯一索引
 *******************************************/
class db
{
    protected $pdo;
    protected $query = ['table' => [], 'field' => [], 'data' => [], 'old_data' => [], 'where' => [], 'whereOr' => [], 'limit' => [], 'page' => [], 'order' => []];
    protected $table = '';
    protected $dbtype;
    protected $dbprefix         = '';
    protected $lastQuery        = '';
    protected $recycle_on       = 1;
    protected $whereField       = 'where';
    protected $allowFields      = false;
    protected $cache_tables     = '';
    protected $cache_base64     = false;
    protected $cache_timeout    = 0;
    protected $cache_createtime = 0;
    protected $random_param     = [
        'mysql'  => 'RAND()',
        'sqlite' => 'RANDOM()',
        'mssql'  => 'RAND()',
    ];

    // 强制不使用缓存
    protected $must_no_cache = false;

    public function __construct($table = '', $extpdo = '', $prefix = null)
    {
        $prepdo = 'db.';
        if ($extpdo) {
            if (strpos($extpdo, '/') !== false || strlen($extpdo) != 32) {
                $extpdo = md5(trim($extpdo, '/'));
            }
            $prepdo .= 'ext.' . $extpdo . '.';
        }
        $this->cache_timeout = set('mysqlcachecycle');
        $this->cache_base64  = 0;
        $this->cache_tables  = set('mysqlcachetables');
        $this->recycle_on    = 0;
        $this->dbprefix      = null === $prefix ? g('sql.prefix') : $prefix;
        $this->dbtype        = 'mysql';
        $this->pdo           = g('pdo');
        if (is_string($this->cache_tables)) {
            $this->cache_tables = explode(',', $this->cache_tables);
        }
        foreach ($this->cache_tables as $k => $v) {
            $this->cache_tables[$k] = $this->dbprefix . $v;
        }
        $this->table = $table;
        $this->table($table);
    }

    //返回pdo对象
    public function pdo()
    {
        return $this->pdo;
    }

    /*
     * 创建一个新表，如果存在该表则放弃
     * @param $name 表名称或表结构
     * @param $structure 表结构，数组 ['字段名称' => [类型,默认值],]
     */
    public function create_table($name = '', $structure = [])
    {
        if (is_array($name)) {
            $structure = $name;
            $name      = '';
        }
        if (!$name && 0 !== $name) {
            $name = $this->table;
        }
        if (in_array($name, $this->table_names())) {
            return false;
        }
        $sql  = '';
        $name = trim($name, '`');
        foreach ($structure as $k => $v) {
            $k = trim($k, '`');
            if (count($v) == 1) {
                $sql .= "`{$k}` {$v[0]},";
            } else {
                $sql .= "`{$k}` {$v[0]} NOT NULL DEFAULT " . (cnum($v[1]) ? $v[1] : "'{$v[1]}'") . ',';
            }
        }
        $sql    = '`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,' . $sql;
        $engine = 'InnoDB';
        if (set('mysql_engine')) {
            $engine = set('mysql_engine');
        }
        $sql = 'CREATE TABLE `' . $this->dbprefix . "{$name}`(" . trim($sql, ',') . ') ENGINE=' . $engine . ' DEFAULT CHARSET=' . (strpos(strtolower(g('sql.charset')), 'utf8mb4') === false ? 'utf8' : 'utf8mb4');
        return $this->pdo->query($sql);
    }

    /*
     * 显示创建一个新表的php代码
     * @param $name 表名称
     */
    public function show_create_table($name = false)
    {
        if (!$name) {
            $name = $this->table;
        }
        $php = '';
        $f   = table($name)->fields(true);
        for ($i = 1; $i < count($f); $i++) {
            $fn         = 'Field';
            $type       = 'Type';
            $null       = 'Null';
            $null_value = 'YES';
            $default    = 'Default';
            if ($f[$i][$null] == $null_value) {
                $php .= "\n	'" . trim($f[$i][$fn], "'") . "' => ['" . trim($f[$i][$type], "'") . "'],";
            } else {
                $php .= "\n	'" . trim($f[$i][$fn], "'") . "' => ['" . trim($f[$i][$type], "'") . "', '" . trim($f[$i][$default], "'") . "'],";
            }
        }
        $table = '';
        if (strpos($name, 'app_') === false) {
            $table = "table('{$name}')";
        } else {
            $dirs = scandir(PK_APP_PATH);
            foreach ($dirs as $dir) {
                if (strpos($name, $dir) === 4) {
                    $table = "aTable('" . substr($name, 4 + strlen($dir) + 1) . "')";
                    break;
                }
            }
            if (!$table) {
                $table = "table('{$name}')";
            }
        }
        $php = "{$table} -> create_table([" . trim($php, ',') . "\n]);";
        return $php;
    }

    /*
     * 获取所有表的名称，不包括系统外的表
     */
    public function table_names()
    {
        switch (strtolower($this->dbtype)) {
            case 'mysql':
                $query = "SHOW TABLES";
                break;
            case 'sqlite':
                $query = "SELECT `name` FROM `sqlite_master` WHERE `type`='table'";
                break;
            case 'mssql':
                $query = "SELECT `Name` FROM `SysObjects` Where `XType`='U'";
                break;
            default:
                error('The database is not supported');
                break;
        }
        $r = $this->pdo->query($query);
        if (!$r) {
            return $r;
        }
        $a = [];
        while ($v = $r->fetch(PDO::FETCH_ASSOC)) {
            $v = current($v);
            if (strpos($v, $this->dbprefix) === 0) {
                $a[] = substr($v, strlen($this->dbprefix));
            }
        }
        $this->resetQuery();
        return $a;
    }

    /*
     * 判断表是否存在
     */
    public function table_exists($name = '')
    {
        if (!$name && 0 !== $name) {
            $name = $this->table;
        }
        $a = $this->table_names();
        if (InArray($a, $name)) {
            return true;
        }
        return false;
    }

    //表选择器
    public function table($tables, $prefix = null)
    {
        if (null === $prefix) {
            $prefix = $this->dbprefix;
        }
        if (is_string($tables)) {
            $tables = explode(',', $tables);
        }
        foreach ($tables as $k => $v) {
            $tables[$k] = $prefix . $v;
            if (strpos($v, ' ') === false) {
                $tables[$k] = '`' . trim($tables[$k], '`') . '`';
            }
        }
        $tables               = implode(',', $tables);
        $this->query['table'] = $tables;
        return $this;
    }

    //获取最后的sql语句
    public function lastQuery($ot = 'query')
    {
        return $this->lastQuery ? $this->lastQuery : $this->query($ot);
    }

    /*
     * 是否清空已输入的查询，默认是
     */
    protected function resetQuery()
    {
        foreach ($this->query as $k => $v) {
            $this->query[$k] = [];
        }
        if ($this->table) {
            $this->table($this->table);
        }
        return $this;
    }

    /*
     * 获取查询数组
     */
    public function getQuery()
    {
        return $this->query;
    }

    /*
     * 设置查询数组
     */
    public function setQuery($query)
    {
        $this->query = $query;
        return $this;
    }

    //拼接sql语句并返回拼接后的sql
    protected function query($ot = 'query')
    {
        //拼接sql语句
        $table = $this->query['table'];
        $field = $this->query['field'] ? implode(',', $this->query['field']) : '*';
        switch ($ot) {
            case 'insert':
                $query = "INSERT INTO {$table}";
                $query .= $this->_query('insert_data');
                break;
            case 'update':
                $query = "UPDATE {$table} SET";
                $query .= $this->_query('update_data,where,whereOr');
                break;
            case 'delete':
                $query = "DELETE FROM {$table}";
                $query .= $this->_query('where,whereOr');
                break;
            default:
                $query = "SELECT {$field} FROM {$table}";
                $query .= $this->_query('where,whereOr,order,page,limit');
                break;
        }
        $this->lastQuery = $query;
        return $query;
    }

    //数据整理
    protected function _query($ot)
    {
        $ot = explode(',', $ot);
        //拼接sql语句
        $where   = $this->query['where'];
        $whereOr = $this->query['whereOr'];
        $limit   = $this->query['limit'];
        $page    = $this->query['page'];
        $order   = $this->query['order'];
        $data    = $this->query['data'];
        $query   = '';
        if (in_array('update_data', $ot)) {
            if ($data) {
                $query = ' ';
                foreach ($data as $k => $v) {
                    $query .= '`' . trim($k, '`') . "`={$v},";
                }
                $query = substr($query, 0, strlen($query) - 1);
            }
        }
        if (in_array('insert_data', $ot)) {
            if ($data) {
                $query = ' ';
                $ks    = '';
                $vs    = '';
                foreach ($data as $k => $v) {
                    $ks .= ',`' . trim($k, '`') . '`';
                    $vs .= ",{$v}";
                }
                $ks = substr($ks, 1);
                $vs = substr($vs, 1);
                $query .= "({$ks}) VALUES ({$vs})";
            }
        }
        if (in_array('where', $ot) || in_array('whereOr', $ot)) {
            if ($where || $whereOr) {
                $query .= ' WHERE ';
            }
            if ($where) {
                //print_r($where);
                $query .= '(';
                foreach ($where as $v) {
                    $query .= "({$v}) AND ";
                }
                $query = substr($query, 0, strlen($query) - 5);
                $query .= ')';
            }
            if ($where && $whereOr) {
                $query .= ' AND ';
            }
            if ($whereOr) {
                $query .= '(';
                foreach ($whereOr as $v) {
                    $query .= "({$v}) OR ";
                }
                $query = substr($query, 0, strlen($query) - 4);
                $query .= ')';
            }
        }
        if (in_array('order', $ot)) {
            if ($order) {
                $query .= ' ORDER BY ';
                foreach ($order as $v) {
                    $query .= "{$v},";
                }
                $query = substr($query, 0, strlen($query) - 1);
            }
        }
        if (in_array('page', $ot) || in_array('limit', $ot)) {
            if ($page || $limit) {
                $query .= ' LIMIT ';
                if ($page) {
                    if (!$limit) {
                        $limit = 10;
                    }
                    $query .= (($page - 1) * $limit) . ',' . $limit;
                } else {
                    if (strpos($limit, ',') === false) {
                        $query .= '0,' . $limit;
                    } else {
                        $query .= $limit;
                    }
                }
            }
        }
        return $query;
    }

    public function mustNoCache($no = true)
    {
        $this->must_no_cache = $no;
        return $this;
    }

    // redis
    protected function redis()
    {
        if (!g('redis.open')) {
            return false;
        }
        $cache_tables = explode(',', g('redis.tables'));
        foreach ($cache_tables as $k => $v) {
            $cache_tables[$k] = $this->dbprefix . $v;
        }
        if (!InArray($cache_tables, trim($this->query['table'], '`'))) {
            return false;
        }
        $redis = new KRedis();
        if (!$redis->connect()) {
            return false;
        }
        return $redis;
    }

    //获取当前缓存最后一次更新的时间
    public function cacheCreatetime()
    {
        if (!$this->cache_timeout || !in_array(trim($this->query['table'], '`'), $this->cache_tables)) {
            //未开启缓存功能
            return false;
        }
        return $this->cache_createtime;
    }

    //获取缓存数据
    public function getCache($query)
    {
        // 不获取缓存
        if ($this->must_no_cache) {
            return false;
        }

        // redis缓存方式，若开启则接管文件缓存
        $redis = $this->redis();
        if ($redis) {
            return $redis->get(md5($query));
        }

        if (!$this->cache_timeout || !in_array(trim($this->query['table'], '`'), $this->cache_tables)) {
            //未开启缓存功能
            return false;
        }

        // 文件缓存方式
        $filemd5  = md5($query . set('key'));
        $filepath = PK_CACHE_PATH . 'sql/' . $filemd5 . '.json';
        if (!file_exists($filepath)) {
            //无缓存文件
            return false;
        }
        if (filemtime($filepath) < time() - $this->cache_timeout) {
            //缓存过期
            return false;
        }
        //该缓存生成的时间
        $this->cache_createtime = filemtime($filepath);
        $r                      = file_get_contents($filepath);
        if ($this->cache_base64) {
            $r = base64_decode($r);
        }
        $r = json_decode($r, true);
        if (!$r) {
            return false;
        }
        return $r;
    }

    public function setCache($query, $data)
    {
        // redis缓存方式，若开启则接管文件缓存
        $redis = $this->redis();
        if ($redis) {
            return $redis->set(md5($query), $data);
        }

        if (!$this->cache_timeout || !in_array(trim($this->query['table'], '`'), $this->cache_tables)) {
            //未开启缓存功能
            return false;
        }
        $filemd5  = md5($query . set('key'));
        $filepath = PK_CACHE_PATH . 'sql/';
        if (!file_exists($filepath) && !mkdir($filepath, 0777, true)) {
            //创建缓存目录失败
            return false;
        }
        $filepath .= $filemd5 . '.json';
        $data = json_encode($data);
        if ($this->cache_base64) {
            $data = base64_encode($data);
        }
        if (!file_put_contents($filepath, $data)) {
            return false;
        }
        //该缓存生成的时间
        $this->cache_createtime = time();
        return true;
    }

    /*
     * 获取表的全部字段名称
     * @param $full 是否获取完整字段信息，默认否
     * @param $table 指定获取的表，默认当前表
     */
    public function fields($full = false, $table = null)
    {
        if (!$table) {
            $table = $this->query['table'];
        }
        $query = '';
        $fn    = '';
        switch (strtolower($this->dbtype)) {
            case 'mysql':
                $query = "SHOW FULL COLUMNS FROM {$table}";
                $fn    = 'Field';
                break;
            case 'sqlite':
                $query = "PRAGMA table_info({$table})";
                $fn    = 'name';
                break;
            case 'mssql':
                $query = "SELECT * FROM `syscolumns` WHERE `id`=object_id({$table}) ORDER BY `colid`";
                $fn    = 'name';
                break;
            default:
                error('The database is not supported');
                break;
        }
        $r = $this->pdo->query($query);
        if (!$r) {
            return $r;
        }
        $a = [];
        while ($v = $r->fetch(PDO::FETCH_ASSOC)) {
            $a[] = $v;
        }
        if (!$full) {
            $b = [];
            foreach ($a as $k => $v) {
                $b[] = $v[$fn];
            }
            $a = $b;
        }
        $this->resetQuery();
        return $a;
    }

    //拿取的字段,exclude为true时是排除这些字段
    public function field($fields, $exclude = false)
    {
        if (is_string($fields)) {
            $fields = explode(',', $fields);
        }
        if ($exclude) {
            $this->query['field'] = $this->fields();
            foreach ($this->query['field'] as $k => $v) {
                if (in_array($v, $fields)) {
                    unset($this->query['field'][$k]);
                }
            }
        } else {
            foreach ($fields as $v) {
                $this->query['field'][] = $v;
            }
        }
        foreach ($this->query['field'] as $k => $v) {
            if (strpos($v, ' ') === false) {
                $this->query['field'][$k] = '`' . trim($v, '`') . '`';
            }
        }
        return $this;
    }

    /* where语句构造,目前最多3个参数,可1/2/3个参数,1可为字符串或数组,2/3必须都为字符串,
     * @param $field
     * @param $op
     * @param $condition
     */
    public function where($field, $op = null, $condition = null)
    {
        if (!$field && Cnum($field, false) === false) {
            return $this;
        }
        $a = [$field];
        if (null !== $op) {
            $a[1] = $op;
        }
        if (null !== $condition) {
            $a[2] = $condition;
        }
        $whereField = $this->whereField;
        switch (count($a)) {
            case 2:
                //$a[0] = "`{$a[0]}`";
                $a[2] = $a[1];
                $a[1] = '=';
            // no break
            case 3:
                $a[0] = [
                    $a[0] => [$a[1], $a[2]],
                ];
                unset($a[1], $a[2]);
            // no break
            case 1:
                if (is_numeric($a[0])) {
                    $a[0] = [
                        'id' => ['=', $a[0]],
                    ];
                }
                if (is_string($a[0])) {
                    $this->query[$whereField][] = $a[0];
                } else {
                    $str = '';
                    foreach ($a[0] as $k => $v) {
                        // 简洁模式
                        if (strpos($k, '&')) {
                            $fields = explode('&', $k);
                            foreach ($fields as $v2) {
                                $this->where([$v2 => $v]);
                            }
                            continue;
                        }
                        if (strpos($k, '|')) {
                            $fields = explode('|', $k);
                            foreach ($fields as $v2) {
                                $this->whereOr([$v2 => $v]);
                            }
                            continue;
                        }
                        // 正常情况
                        if (is_string($v) || is_numeric($v)) {
                            $v = ['=', $v];
                        }
                        if (!is_array($v[0])) {
                            $v = [$v];
                        }
                        foreach ($v as $_v) {
                            if (in_array(strtoupper($_v[0]), ['IN', 'NOT IN'])) {
                                $_v[0] = strtoupper($_v[0]);
                                if (is_array($_v[1])) {
                                    $_v[1] = implode(',', $_v[1]);
                                }
                                $_v[1] = "('" . str_replace(',', "','", str_replace('\'', '', $_v[1])) . "')";
                            } elseif (in_array(strtoupper($_v[0]), ['BETWEEN', 'NOT BETWEEN'])) {
                                $_v[0] = strtoupper($_v[0]);
                            } else {
                                $_v[1] = mysqlstr($_v[1]);
                            }
                            $str .= ' AND `' . trim($k, '`') . '`' . " {$_v[0]} {$_v[1]}";
                        }
                    }
                    if ($str) {
                        $str                        = substr($str, 5);
                        $this->query[$whereField][] = $str;
                    }
                }
                break;
        }
        return $this;
    }

    public function whereOr($field, $op = null, $condition = null)
    {
        $this->whereField = 'whereOr';
        $this->where($field, $op, $condition);
        $this->whereField = 'where';
        return $this;
    }

    public function limit($limit)
    {
        $this->query['limit'] = Cnum($limit);
        return $this;
    }

    //分页
    public function page($page, $limit = null)
    {
        $this->query['page'] = Cnum($page);
        if ($limit) {
            $this->limit($limit);
        }
        return $this;
    }

    //排序
    public function order($field, $order = null)
    {
        $a = [$field];
        if (null !== $order) {
            $a[1] = $order;
        }
        switch (count($a)) {
            case 2:
                $a[0] = '`' . trim($a[0], '`') . '` ' . strtoupper($a[1]);
            // no break
            case 1:
                if (is_string($a[0])) {
                    $_str   = '';
                    $orders = explode(',', $a[0]);
                    foreach ($orders as $_order) {
                        $_a = explode(' ', $_order);
                        if (count($_a) == 2) {
                            $_str .= ',`' . trim($_a[0], '`') . '` ' . strtoupper($_a[1]);
                        } else {
                            $_str .= ",{$_order}";
                        }
                    }
                    $_str = trim($_str, ',');
                    //print_r($_str."\n");
                    $this->query['order'][] = $_str;
                } else {
                    $str = '';
                    foreach ($a[0] as $k => $v) {
                        $str .= ',`' . trim($k, '`') . '` ' . strtoupper($v);
                    }
                    $str                    = substr($str, 1);
                    $this->query['order'][] = $str;
                }
                break;
        }
        return $this;
    }

    //更新或插入数据整理
    public function data($field, $value = null)
    {
        $a = [$field];
        if (null !== $value) {
            $a[1] = $value;
        }
        switch (count($a)) {
            case 2:
                $a[0] = [$a[0] => $a[1]];
            // no break
            case 1:
                if (!is_array($a[0])) {
                    break;
                }
                foreach ($a[0] as $k => $v) {
                    if (is_array($this->allowFields)) {
                        //排除非白名单的字段
                        if (!in_array($k, $this->allowFields)) {
                            continue;
                        }
                    }
                    if (is_string($v) || is_numeric($v)) {
                        $this->query['old_data'][$k] = $v;
                        $this->query['data'][$k]     = mysqlstr($v);
                    } elseif (is_array($v) && count($v) == 2) {
                        $this->query['old_data'][$k] = '`' . trim($k, '`') . '`' . "{$v[0]}{$v[1]}";
                        $this->query['data'][$k]     = '`' . trim($k, '`') . '`' . "{$v[0]}" . mysqlstr($v[1]);
                    }
                }
                break;
        }
        return $this;
    }

    /**
     * 获取上条sql命令错误信息，默认返回错误信息字符串
     * @param boolean $all 默认false，false返回错误的消息，true返回错误详情数组
     */
    public function error($all = false)
    {
        $errorInfo = $this->pdo->errorInfo();
        return $all ? $errorInfo : $errorInfo[2];
    }

    //读取一条记录,或获取单个字段的值
    public function find($field = null)
    {
        if ($field) {
            $this->field($field);
        }
        //防止存在多个记录,这里只取最新的一条记录
        $this->limit(1)->page(1, 1)->order('id', 'desc');
        $query   = $this->query('query');
        $cache_r = $this->getCache($query);
        if (false !== $cache_r) {
            //有缓存
            $r = $cache_r;
        } else {
            $r = $this->pdo->query($query);
            if (!$r) {
                return [];
            }
            $r = $r->fetch(PDO::FETCH_ASSOC);
            //存储缓存
            $this->setCache($query, $r);
        }
        $this->resetQuery();
        if ($field) {
            if (!$r) {
                return $r;
            }
            return current($r);
        }
        return $r;
    }

    //读取记录集合
    public function select()
    {
        $query   = $this->query('query');
        $cache_r = $this->getCache($query);
        if (false !== $cache_r) {
            //有缓存
            $a = $cache_r;
        } else {
            $r = $this->pdo->query($query);
            if (!$r) {
                return [];
            }
            $a = [];
            while ($v = $r->fetch(PDO::FETCH_ASSOC)) {
                $a[] = $v;
            }
            //存储缓存
            $this->setCache($query, $a);
        }
        $this->resetQuery();
        //输出数据
        return $a;
    }

    // 随机读取记录集合,$n为数量
    public function random($n = 0)
    {
        // 临时保存query参数
        $query                = $this->query;
        $this->query['order'] = [];
        $this->order($this->random_param[strtolower($this->dbtype)]);
        if ($n) {
            $this->limit($n);
        }
        //print_r($this -> query('query'));
        //exit;
        $r = $this->pdo->query($this->query('query'));
        if (!$r) {
            return [];
        }
        $a   = [];
        $ids = [];
        while ($v = $r->fetch(PDO::FETCH_ASSOC)) {
            if (in_array($v['id'], $ids)) {
                continue;
            }
            $ids[] = $v['id'];
            $a[]   = $v;
        }
        $this->resetQuery();
        // 判断是否取够了随机数
        if ($n && count($ids) < $n) {
            $_n          = $n - count($ids);
            $this->query = $query;
            $r           = $this->where('id', 'not in', $ids)->limit($_n)->order('id desc')->select();
            $a           = array_merge($a, $r);
        }
        //输出数据
        return $a;
    }

    //更新和插入时允许的字段白名单
    public function allowFields($fields = false)
    {
        if (!$fields) {
            return $this;
        }
        if (true === $fields) {
            $fields = $this->fields();
        }
        if (is_string($fields)) {
            $fields = explode(',', $fields);
        }
        if (!is_array($fields)) {
            return $this;
        }
        $this->allowFields = $fields;
        return $this;
    }

    /**
     * 更新数据
     * @param array/null $data 待更新的数据，若包含id则为更新该id记录的数据，否则需要配合where使用
     * @return boolean true/false
     */
    public function update($data = null)
    {
        if ($data) {
            $id = 0;
            if (isset($data['id'])) {
                $id = $data['id'];
                unset($data['id']);
            }
            $this->data($data);
            if (!$this->query['where'] && !$this->query['whereOr']) {
                if (!$id) {
                    return false;
                }
                $this->where('id', $id);
            }
        }
        // print_r(microtime());
        // print_r($this -> query('update'));
        $r = $this->pdo->query($this->query('update'));
        // print_r($this -> lastQuery());
        // print_r(microtime());
        $this->resetQuery();
        if (!$r) {
            return $r;
        }
        return true;
    }

    //更新多条数据,返回更新成功的条数
    public function updateAll($datas)
    {
        $i = 0;
        foreach ($datas as $data) {
            if ($this->allowFields(true)->update($data)) {
                $i++;
            }
            $this->query['where']   = '';
            $this->query['whereOr'] = '';
        }
        $this->resetQuery();
        return $i;
    }

    //添加数据
    public function insert($data = null)
    {
        if ($data) {
            $this->data($data);
        }
        $r = $this->pdo->query($this->query('insert'));
        $this->resetQuery();
        if (!$r) {
            return $r;
        }
        return true;
    }

    //添加多条数据,返回添加成功的条数
    public function insertAll($datas)
    {
        $i = 0;
        foreach ($datas as $data) {
            if ($this->allowFields(true)->insert($data)) {
                $i++;
            }
        }
        $this->resetQuery();
        return $i;
    }

    //添加数据并返回该数据的id
    public function insertGetId($data = null)
    {
        if (!$data) {
            $fd = $this->query['old_data'];
        }
        $r = $this->insert($data);
        if (!$r) {
            return $r;
        }
        $this->resetQuery();
        $data   = $data ? $data : $fd;
        $fields = $this->fields();
        foreach ($data as $k => $v) {

            if (!InArray($fields, $k) || strpos($v, '.') !== false) {
                unset($data[$k]);
            }
        }
        if ($data) {
            $r = $this->where($data)->find('id');
        } else {
            $r = $this->find('id');
        }
        $this->resetQuery();
        return $r;
    }

    //计算总数
    public function count($field = '*')
    {
        $this->query['field'] = ["count({$field}) as `count`"];
        $r                    = $this->pdo->query($this->query('query'));
        if (!$r) {
            return 0;
        }
        $r = $r->fetch(PDO::FETCH_ASSOC);
        $this->resetQuery();
        return $r['count'];
    }

    //删除记录,ids为删除的id值
    public function delete($ids = null)
    {
        if ($ids) {
            $this->where('id', 'in', $ids);
        }
        $r = $this->pdo->query($this->query('delete'));
        $this->resetQuery();
        return $r;
    }

    /*
     * 获取数据库版本
     */
    public function version()
    {
        switch (strtolower($this->dbtype)) {
            case 'mysql':
                $query = 'SELECT VERSION()';
                break;
            case 'sqlite':
                $query = 'SELECT sqlite_version()';
                break;
            case 'mssql':
                $query = "SELECT DATABASEPROPERTYEX('master','version')";
                break;
            default:
                error('The database is not supported');
                break;
        }
        $r = $this->pdo->query($query);
        if (!$r) {
            return '';
        }
        while ($v = $r->fetch(PDO::FETCH_ASSOC)) {
            return strtoupper($this->dbtype) . ' ' . current($v);
        }
    }
}
