<?php

namespace Qii\Driver;

class Base
{
    const VERSION = '1.2';
    public $cache;
    public $language;
    protected $_query = array(
        "INSERT" => "INSERT INTO %s(%s) VALUES('%s')",
        "REPLACE" => "REPLACE %s (%s) VALUES('%s')",
        "SELECT" => "SELECT %s FROM %s",
        "LEFT_JOIN" => " LEFT JOIN %s ON %s",
        "RIGHT_JOIN" => " RIGHT JOIN %s ON %s",
        "UPDATE" => "UPDATE %s SET ",
        "DELETE" => "DELETE FROM %s %s",
        "WHERE" => " WHERE %s",
        "OR" => " `%s` = '%s' ",
        "LIKE" => " `%s` LIKE '%s'",
        "ORDER" => " ORDER BY %s %s",
        "GROUP" => " GROUP BY %s",
        "LIMIT" => " LIMIT %d, %d"
    );
    private $setArray = array();
    public $modelSQL = "";
    protected $fields;
    protected $groupBy;
    protected $limit;
    protected $orderBy;
    public $load;
    public $where = null;
    public $join = null;
    /**
     * @var string $response Response对象
     */
    public $response;

    //方法对应的别名
    protected $_modelAlias = array('selectRows' => 'selectAll', 'select' => 'selectRow', 'getOne' => 'selectOne', 'getRow' => 'selectRow', 'getAll' => 'selectAll', 'remove' => 'deleteRows');

    public function __construct()
    {
        $this->language = \Qii\Autoloader\Psr4::getInstance()->loadClass('Qii\Language\Loader');
        $this->load = \Qii\Autoloader\Psr4::getInstance()->loadClass('\Qii\Autoloader\Loader');
        $this->response = new \Qii\Driver\Response();
    }

    /**
     * 获取数据库中所有的数据表
     * @return array
     */
    public function getAllDatabases()
    {
        $sql = "SHOW DATABASES";
        $rs = $this->setQuery($sql);

        $database = array();
        while ($row = $rs->fetch()) {
            $database[] = $row['Database'];
        }
        return $database;
    }

    /**
     * 数据库中是否包含指定库
     * @param string $database 数据库名
     * @return bool
     */
    public function hasDatabase($database)
    {
        if (!$database) return false;
        $sql = "SHOW DATABASES LIKE '" . $database . "'";
        $rs = $this->setQuery($sql);
        while ($row = $rs->fetch()) {
            $val = array_values($row);
            if (in_array($database, $val)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取当前数据库中所有的表
     * @param null|string $database 数据库
     * @return array
     */
    public function getAllTables($database = null)
    {
        if ($database) {
            $this->setQuery('USE ' . $database);
        }
        $sql = "SHOW TABLES";
        $rs = $this->setQuery($sql);
        $tables = array();
        while ($row = $rs->fetch()) {
            if (is_array($row)) {
                foreach ($row AS $val) {
                    $tables[] = $val;
                }
            }
        }
        return $tables;
    }

    /**
     * 获取指定数据表的所有字段
     * @param string $table 表名
     * @param string $database 数据库名
     * @param string $autoIncr 自动增长的序号
     * @return array
     */
    public function getTableInfo($table, $database = null, $autoIncr = null)
    {
        if (!$database) $database = $this->currentDB;
        $sql = "SELECT * from information_schema.COLUMNS where table_name = '" . $table . "' and table_schema = '" . $database . "'";
        $data = ['fields' => [],
            'rules' => [
                'pri' => [], 'required' => []
            ]
        ];

        $rs = $this->setQuery($sql);
        while ($row = $rs->fetch()) {
            $data['fields'][] = $row['COLUMN_NAME'];
            if ($row['EXTRA']) {
                $data['rules']['extra'][$row['EXTRA']][] = $row['COLUMN_NAME'];
            }
            if ($row['COLUMN_KEY'] == 'PRI') {
                $data['rules']['pri'][] = $row['COLUMN_NAME'];
                $data['rules']['required'][] = $row['COLUMN_NAME'];
            }
            if ($row['IS_NULLABLE'] == 'NO') {
                $data['rules']['required'][] = $row['COLUMN_NAME'];
            }
            if (in_array($row['DATA_TYPE'], ['varchar', 'char'])) {
                $data['rules']['maxlength'][$row['COLUMN_NAME']] = $row['CHARACTER_MAXIMUM_LENGTH'];
            }
            if (in_array($row['DATA_TYPE'], ['mediumtext', 'TINYTEXT', 'text', 'longtext'])) {
                $data['rules']['text'][] = $row['COLUMN_NAME'];
            }
            if (in_array($row['DATA_TYPE'], ['bigint', 'int', 'smallint', 'tinyint', 'integer'])) {
                preg_match('/[\d]{1,}/', $row['COLUMN_TYPE'], $matches);
                $data['rules']['int'][$row['COLUMN_NAME']] = $matches[0];
                $data['rules']['number'][] = $row['COLUMN_NAME'];
            }
            if (in_array($row['DATA_TYPE'], ['float', 'double', 'decimal'])) {
                $data['rules']['float'][$row['COLUMN_NAME']] = $this->getValueFromBrackets($row['COLUMN_TYPE']);
            }
            if (in_array($row['DATA_TYPE'], ['timestamp', 'datatime'])) {
                $data['rules']['timestamp'][] = $row['COLUMN_NAME'];
            }
            if (in_array($row['DATA_TYPE'], ['enum', 'set'])) {
                $data['rules']['sets'][$row['COLUMN_NAME']] = $this->getValueFromBrackets($row['COLUMN_TYPE']);
            }
            if (isset($row['COLUMN_DEFAULT'])) {
                $data['rules']['default'][$row['COLUMN_NAME']] = $row['COLUMN_DEFAULT'];
            }
        }
        $data['sql'] = $this->getTableSQL($table, $database, $autoIncr);
        return $data;
    }

    /**
     * 从括号中获取指定的值
     * @param string $str 需要获取的内容
     * @return array
     */
    public function getValueFromBrackets($str)
    {
        preg_match("/(?:\()(.*)(?:\))/i", $str, $matches);
        $str = $matches[1];
        $a = explode(",", $str);
        for ($i = 0; $i < count($a); $i++) {
            $this->removeQuote($a[$i]);//从字符串中去除单引号
        }
        return $a;
    }

    /**
     * 去除双引号
     * @param string $str 去除双引号
     */
    public function removeQuote(&$str)
    {
        if (preg_match("/^\'/", $str)) {
            $str = substr($str, 1, strlen($str) - 1);
        }
        if (preg_match("/\'$/", $str)) {
            $str = substr($str, 0, strlen($str) - 1);
        }
        return $str;
    }

    /**
     * 查询数据库中是否有指定的表
     * @param string $tableName 表名
     * @param null|string $database 数据库
     * @return bool
     */
    public function hasTable($tableName, $database = null)
    {
        if ($database) {
            $this->setQuery('USE ' . $database);
        }
        $sql = "SHOW TABLES LIKE '" . $tableName . "'";
        $rs = $this->setQuery($sql);

        $tables = array();
        while ($row = $this->fetch($rs)) {
            if (is_array($row)) {
                foreach ($row AS $val) {
                    if ($val == $tableName) return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取创建表的SQL语句
     * @param string $tableName 表名
     * @param null|string $database 数据库
     * @param int|null $autoIncr 自增长的值，null的话就不使用
     * @return string
     */
    public function getTableSQL($tableName, $database = null, $autoIncr = null)
    {
        if ($database) {
            $this->setQuery('USE ' . $database);
        }
        $row = $this->getRow("SHOW CREATE TABLE `" . $tableName . "`");
        if (!$row) {
            throw new \Exception('数据表不存在', __LINE__);
        }
        $sql = $row['Create Table'];
        if ($autoIncr === null) {
            return $sql;
        }
        return preg_replace("/AUTO_INCREMENT=[\d]{1,}/", "AUTO_INCREMENT=" . intval($autoIncr), $sql);
    }

    /**
     * 通过数据表名称获取规则
     * @param string $table 表名
     * @param string $database 数据库名
     */
    public function buildRulesForTable($table, $database = null)
    {
        if (!$database) $database = $this->currentDB;
        $tableInfo = $this->getTableInfo($table, $database);
        $rules = new \Qii\Base\Rules();
        $rules->addFields($tableInfo['fields']);
        if ($tableInfo['rules']['required']) {
            $rules->addForceValidKey($tableInfo['rules']['required']);
        }
        if (isset($tableInfo['rules']['number'])) {
            foreach ($tableInfo['rules']['number'] as $key => $value) {
                $rules->addRules($value, 'number', true, $value . '字段必须是数字');
            }
        }
        if (isset($tableInfo['rules']['maxlength'])) {
            foreach ($tableInfo['rules']['maxlength'] as $key => $value) {
                $rules->addRules($key, 'maxlength', $value, $key . '字段内容长度不能大于' . $value . '个字符');
            }
        }
        if (isset($tableInfo['rules']['timestamp'])) {
            foreach ($tableInfo['rules']['timestamp'] as $key => $value) {
                $rules->addRules($value, 'datetime', true, $value . '字段必须为日期格式');
            }
        }
        return $rules;
    }

    final public function getAlias($alias)
    {
        return isset($this->_modelAlias[$alias]) ? $this->_modelAlias[$alias] : null;
    }

    /**
     * 设置Cache
     *
     * @param String $cache
     * @param Array $policy
     */
    final public function setCache($cache, $policy)
    {
        \Qii\Autoloader\Import::requires(Qii_DIR . DS . 'Qii' . DS . 'Cache.php');
        $this->cache = \Qii\Autoloader\Psr4::loadClass('\Qii\Cache', $cache)->initialization($policy);//载入cache类文件
    }

    /**
     * 缓存内容
     *
     * @param String $id
     * @param Array $value
     * @return Bool
     */
    final public function cache($id, $value)
    {
        return $this->cache->set($id, $value);
    }

    /**
     * 获取缓存的类
     */
    final public function getCache()
    {
        return $this->cache;
    }

    /**
     * 获取缓存内容
     *
     * @param String $id
     * @return Array
     */
    final public function getCacheData($id)
    {
        return $this->cache->get($id);
    }

    /**
     * 获取表的名称
     * @param String $table
     * @return String
     */
    public function getTable($table)
    {
        list($database, $tableName) = array_pad(explode('.', $table), 2, '');

        if ($tableName) {
            $tableName = stristr($tableName, '`') || stristr($tableName, " ") ? $tableName : '`'. $tableName .'`';
            return "`{$database}`.`{$tableName}`";
        }
        $table = stristr($table, '`') || stristr($tableName, " ")  ? $table : '`'. $table .'`';
        return $table;
    }

    public function setLanguage()
    {
        $this->language = \Qii\Autoloader\Psr4::loadClass('Qii\Language\Loader');
    }

    /**
     *
     * Insert Object
     * @param String $table
     * @param Array|Object $dataArray
     */
    final function insertObject($table, $dataArray)
    {
        if (empty($table)) {
            return -1;
        }
        if (sizeof($dataArray) > 0 || (is_object($dataArray) && get_object_vars($dataArray)) > 0) {
            $keys = array();
            $values = array();
            foreach ($dataArray AS $key => $value) {
                $keys[] = $key;
                if (is_array($value)) {
                    throw new \Qii\Exceptions\InvalidFormat(_i('Invalid %s format', $key), __LINE__);
                }
                $values[] = $this->setQuote($value);
            }

            $this->modelSQL = $sql = "INSERT INTO " . $this->getTable($table) . "(`" . join("`, `", $keys) . "`) VALUES('" . join("', '", $values) . "')";
            $this->setQuery($sql);
            $this->cleanData();
            $this->setError();
            return $this->lastInsertId();
        }
        return -2;
    }

    /**
     * 左连表
     *
     * @param string $table 表名
     * @param string $on on条件
     * @return $this
     */
    final function leftJoinObject($table, $on)
    {
        if(empty($table) || empty($on)) return $this;

        $this->join .= sprintf($this->_query['LEFT_JOIN'], $table, $on);
        return $this;
    }

    /**
     * 右连表
     *
     * @param string $table 表名
     * @param string $on on条件
     * @return $this
     */
    final function rightJoinObject($table, $on)
    {
        if(empty($table) || empty($on)) return $this;

        $this->join .= sprintf($this->_query['RIGHT_JOIN'], $table, $on);
        return $this;
    }

    /**
     *
     * Replace Object
     * @param String $table
     * @param Array|Object $dataArray
     */
    final function replaceObject($table, $dataArray)
    {
        if (empty($table)) {
            return -1;
        }
        if (sizeof($dataArray) > 0 || get_object_vars($dataArray) > 0) {
            $keys = array();
            $values = array();
            foreach ($dataArray AS $key => $value) {
                $keys[] = $key;
                if (is_array($value)) {
                    throw new \Qii\Exceptions\InvalidFormat(_i('Invalid %s format', $key), __LINE__);
                }
                $values[] = $this->setQuote($value);
            }
            $this->modelSQL = $sql = "REPLACE INTO " . $this->getTable($table) . "(`" . join("`, `", $keys) . "`) VALUES('" . join("', '", $values) . "')";
            $rs = $this->setQuery($sql);
            $this->cleanData();
            $this->setError();
            return $this->AffectedRows($rs);
        }
        return -2;
    }

    /**
     *
     * Update data
     * @param String $table
     * @param Array|Objct $dataArray
     * @param Array $keys
     */
    final function updateObject($table, $dataArray, $keys = array())
    {
        if (empty($table) || !is_array($keys)) {
            return -1;
        }
        if (sizeof($dataArray) > 0 || get_object_vars($dataArray) > 0) {
            $values = array();
            $where = array();
            foreach ($dataArray AS $key => $value) {
                if (is_array($value)) {
                    throw new \Qii\Exceptions\InvalidFormat(_i('Invalid %s format', $key), __LINE__);
                }
                $value = $this->setQuote($value);
                if (in_array($key, $keys)) {
                    $where[] = "`{$key}` = '" . $value . "'";
                } else {
                    $values[] = "`{$key}` = '" . $value . "'";
                }
            }
            //$keys为key => value的方式，就直接用keys
            if (empty($where) && count($keys) > 0) {
                foreach ($keys as $key => $value) {
                    $value = $this->setQuote($value);
                    $where[] = "`{$key}` = '" . $value . "'";
                }
            }
            $whereSQL = $this->where;
            if (sizeof($where) > 0) {
                $whereSQL = $this->where ? $this->where . " AND (" . join(" AND ", $where) . ")" : " WHERE " . join(" AND ", $where);
            }
            $this->modelSQL = $sql = "UPDATE " . $this->getTable($table) . " SET " . join(", ", $values) . $whereSQL;
            $rs = $this->setQuery($sql);
            $this->cleanData();
            $this->setError();
            return $this->AffectedRows($rs);
        }
        return 0;
    }

    /**
     *
     * 删除数据
     * @param String $table
     * @param Array $keys
     */
    final function deleteObject($table, $keys = array())
    {
        if (empty($table)) {
            return -1;
        }
        $where = array();
        if (sizeof($keys) > 0 || (is_a($keys, 'stdclass') && get_object_vars($keys))) {
            foreach ($keys AS $k => $v) {
                $where[] = "`{$k}` = '" . $this->setQuote($v) . "'";
            }
        }
        $whereSQL = $this->where;
        if (sizeof($where) > 0) {
            $whereSQL = $this->where ? $this->where . " AND (" . join(" AND ", $where) . ")" : " WHERE " . join(" AND ", $where);
        }
        $this->modelSQL = $sql = "DELETE FROM " . $this->getTable($table) . " " . $whereSQL;
        $rs = $this->query($sql);
        $this->cleanData();
        $this->setError();
        return $this->AffectedRows($rs);
    }

    /**
     * 需要清除的数据
     *
     * @return array
     */
    final function cleanOptions()
    {
        return array('fields', 'where', 'groupBy', 'orderBy', 'limit', 'setArray', 'join');
    }

    /**
     * 清除数据
     *
     */
    final function cleanData()
    {
        $array = $this->cleanOptions();
        foreach ($array AS $k) {
            if (is_array($this->$k)) {
                $this->$k = array();
            } else {
                $this->$k = null;
            }
        }
    }

    /**
     *
     * 查询的字段
     * @param String $fields
     */
    final function fields($fields = "*")
    {
        $this->fields = null;
        if (empty($fields)) $fields = "*";
        if (is_array($fields)) {
            foreach($fields as $key => $val)
            {
                $alias = explode('.', $val);
                if(count($alias) > 1)
                {
                    $fields[$key] = $alias[0] . ".`".join(".", array_slice($alias, 1))."`";
                }
            }
            $fields = join(',', $fields);
        }
        $this->fields = $fields;
        return $this;
    }

    /**
     *
     * GROUP BY方法
     * @param String $fields
     */
    final function groupBy($fields)
    {
        $this->groupBy = null;
        if (!empty($fields)) {
            $fields = is_array($fields) ? join(', ', $fields) : $fields;
            $this->groupBy = sprintf($this->_query['GROUP'], $fields);
        }
        return $this;
    }

    /**
     *
     * 插入数据用
     * @param Array $array
     */
    final function dataArray($array)
    {
        $this->fileds = null;
        if (is_array($array)) {
            $tmpArray = array();
            foreach ($array AS $k => $v) {
                $tmpArray['k'][] = $this->setQuote($k);
                $tmpArray['v'][] = $this->setQuote($v);
            }
            $this->fileds = $tmpArray;
        }
        return $this;
    }

    /**
     *
     * Order By函数
     * @param String $field
     * @param String $orderBy
     */
    final function orderBy($field, $orderBy)
    {
        if (!empty($field)) return $this;

        if ($this->orderBy != '') {
            $this->orderBy .= $field . ' ' . $orderBy;
        } else {
            $this->orderBy = sprintf($this->_query['ORDER'], $field, $orderBy);
        }
    }

    /**
     * 多个order by条件
     */
    final function orderByArr($map)
    {
        if (empty($map)) return $this;
        foreach ($map AS $val) {
            $this->orderBy($val['field'], $val['orderBy']);
        }
        return $this;
    }

    /**
     * order by
     * @param string order by
     */
    final function orderByStr($orderBy)
    {
        if (!$orderBy) return $this;
        $this->orderBy = $orderBy;
        return $this;
    }

    /**
     *
     * Limit函数，如果省略第二个参数则第一个为0，第二个参数值取第一个
     * @param Int $limit
     * @param Int $offset
     */
    final function limit($limit, $offset = 0)
    {
        $this->limit = null;
        if ($limit !== '') {
            if (!$offset) {
                $this->limit = sprintf($this->_query["LIMIT"], 0, $limit);
            } else {
                $this->limit = sprintf($this->_query["LIMIT"], $limit, $offset);
            }
        }
        return $this;
    }

    /**
     * 创建Like查询条件
     * @param string | array $like like的条件
     */
    final function like($like)
    {
        if (empty($like)) return $this;
        $likeArray = array();
        if ($like && !is_array($like)) {
            $likeArray[] = $like;
        } else {
            foreach ($like AS $key => $val) {
                if(stristr($key, '.')) {
                    $likeArray[] = sprintf("%s LIKE '%s'", $key, "%" . $this->setQuote($val) . "%");
                }else{
                    $likeArray[] = sprintf($this->_query['LIKE'], $key, "%" . $this->setQuote($val) . "%");
                }
            }
        }
        if (count($likeArray) > 0) {
            $likeSQL = join(" OR ", $likeArray);
            if (!$this->where) {
                $this->where = sprintf($this->_query["WHERE"], $likeSQL);
            } else {
                $this->where .= ' AND (' . $likeSQL . ')';
            }
        }
        return $this;
    }
    /**
     * 不包含的条件
     * @param array $where 条件
     * @return $this
     */
    final function exclude($where)
    {
        if (empty($where)) return $this;
        $whereArray = array();
        if ($where && !is_array($where)) {
            $whereArray[] = $where;
        } else {
            foreach ($where AS $key => $val) {
            	$whereArray[] = sprintf("%s != '%s'", $key, $this->setQuote($val));
            }
        }
        if (count($whereArray) > 0) {
            $whereSQL = join(" AND ", $whereArray);
            if (!$this->where) {
                $this->where = sprintf($this->_query["WHERE"], $whereSQL);
            } else {
                $this->where .= ' AND (' . $whereSQL . ')';
            }
        }
        return $this;
    }

    /**
     * 传的条件为数组
     * @param  Array $where 条件
     * @return Object       对象本身
     */
    final function whereArray($where)
    {
        $this->where = null;
        if (!empty($where)) {
            $whereArray = array();
            foreach ($where AS $k => $v) {
                $v = $this->setQuote($v);
                if(stristr($k, '.')) {
                    $whereArray[] = " {$k} = '{$v}'";
                }else{
                    $whereArray[] = " `{$k}` = '{$v}'";
                }
            }
            if (sizeof($whereArray) > 0) {
                $whereSQL = join(" AND ", $whereArray);
                if (!$this->where) {
                    $this->where = sprintf($this->_query["WHERE"], $whereSQL);
                } else {
                    $this->where .= " AND (" . $whereSQL . ")";
                }
            }
        }
        return $this;
    }

    /**
     *
     * WHERE 子句
     * @param String $where
     */
    final function where($where)
    {
        if (is_array($where)) return $this->whereArray($where);
        $this->where = null;
        if (!empty($where)) {
            $this->where = sprintf($this->_query["WHERE"], $where);
        }
        return $this;
    }
    /**
     * 操作where条件语句
     *
     * @param $and
     * @param string $insideBrackets or条件里边的操作符
     * @param string $outsideBrackets 链接or条件的操作符
     * @return $this
     */
    final function and($and, $insideBrackets = "OR", $outsideBrackets = "AND") {
        return $this->or($and, $insideBrackets, $outsideBrackets);
    }
    /**
     * 操作where条件语句
     *
     * @param $or
     * @param string $insideBrackets or条件里边的操作符
     * @param string $outsideBrackets 链接or条件的操作符
     * @return $this
     */
    final function andStr($or, $insideBrackets = "AND", $outsideBrackets = "OR") {
        return $this->orStr($or, $insideBrackets, $outsideBrackets);
    }
    /**
     * 操作where条件语句
     *
     * @param $or
     * @param string $insideBrackets or条件里边的操作符
     * @param string $outsideBrackets 链接or条件的操作符
     * @return $this
     */
    final function or($or, $insideBrackets = "AND", $outsideBrackets = "OR")
    {
        if(empty($or)) return $this;
        $orCond = array();
        if(is_array($or)) {
            foreach($or as $key => $val) {
                $orCond[] = sprintf($this->_query['OR'], $key, $this->setQuote($val));
            }
        }
        else
        {
            $orCond[] = $or;
        }
        if(!empty($this->where)) {
            $this->where .= " ". $outsideBrackets. "  (". join(" ". $insideBrackets . " ", $orCond) .")";
        }else{
            $this->where = " WHERE (". join(" ". $insideBrackets . " ", $orCond) .")";
        }
        return $this;
    }
    /**
     * 操作where条件语句
     *
     * @param $or
     * @param string $insideBrackets or条件里边的操作符
     * @param string $outsideBrackets 链接or条件的操作符
     * @return $this
     */
    final function orStr($or, $insideBrackets = "AND", $outsideBrackets = "OR") {
        if(empty($or)) return $this;
        if(is_array($or)) {
            $or = join(" ". $insideBrackets . " ", $or);
        }
        if(!empty($this->where)) {
            $this->where .= " ". $outsideBrackets ." (". $or . ")";
        }
        return $this;
    }

    /**
     * 创建插入表的SQL
     */
    final function createInsertSQL($table)
    {
        $sql = sprintf($this->_query['INSERT'], $table, join(",", $this->fileds['k']), join("', '", $this->fileds['v']));
        $this->cleanData();
        return $sql;
    }

    /**
     *
     * 插入数据到指定表中
     * @param String $table
     */
    final function insertRow($table)
    {
        $this->modelSQL = $sql = $this->createInsertSQL($table);
        $this->setQuery($sql);
        return $this->lastInsertId();
    }

    /**
     * 创建replace object SQL
     *
     * @param string $table 表名
     * @return string
     */
    final function createReplaceSQL($table)
    {
        $sql = sprintf($this->_query['REPLACE'], $table, join(",", $this->fileds['k']), join("', '", $this->fileds['v']));
        $this->cleanData();
        return $sql;
    }

    /**
     *
     * Replace方法
     * @param String $table
     */
    final function replaceRow($table)
    {
        $this->modelSQL = $sql = $this->createReplaceSQL($table);
        return $this->exec($sql);
    }

    /**
     *
     * 查询一行
     * @param String $table
     */
    final function selectRow($table)
    {
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        $this->cleanData();
        return $this->getRow($sql);
    }


    /**
     *
     * 查询一行
     * @param String $table
     */
    final function selectOne($table)
    {
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->getOne($sql);
    }

    /**
     * 创建SELECT SQL
     */
    final function createSelectSQL($table)
    {

        if(stristr($table, '.') == false
            && stristr($table, '`') == false
            && stristr($table, ' ') == false
        ) {
            $table = '`'. $table .'`';
        }
        $sql = sprintf($this->_query['SELECT'], ((trim($this->fields) != '') ? $this->fields : "*"), $table) . $this->join . $this->where . $this->groupBy . $this->orderBy . $this->limit;
        $this->cleanData();
        return $sql;
    }

    /**
     *
     * 查询所有
     * @param String $table 数据表名称
     * @return Array
     */
    final function selectAll($table)
    {
        $this->modelSQL = $sql = $this->createSelectSQL($table);
        return $this->getAll($sql);
    }

    /**
     * 返回resource资源
     * @param string $table 数据表名称
     */
    final function rs($table)
    {
        $this->modelSQL = $sql = sprintf($this->_query['SELECT'], ((trim($this->fields) != '') ? $this->fields : "*"), $table) . $this->join . $this->where . $this->groupBy . $this->orderBy . $this->limit;
        $this->cleanData();
        return $this->setQuery($sql);
    }

    /**
     * 将指定字段减指定值
     *
     * @param array $data 数据
     * @return $this
     */
    final function downsetCounter($data)
    {
        if (is_array($data)) {
            foreach ($data AS $k => $value) {
                $this->setArray[] = $k . "=" . $k . '-' . $value;
            }
        }
        $this->set(null);
        return $this;
    }

    /**
     * 将指定字段加指定值
     *
     * @param $data
     * @return $this
     */
    final function upsetCounter($data)
    {
        if (is_array($data)) {
            foreach ($data AS $k => $value) {
                $this->setArray[] = $k . "=" . $k . '+' . $value;
            }
        }
        $this->set(null);
        return $this;
    }

    /**
     * 更新数据时候用，方法同setData
     * @param Array $data
     */
    final function set($data)
    {
        return $this->setData($data);
    }

    /**
     *
     * 更新数据时候用
     * @param Array $data
     * @return $this
     */
    final function setData($data)
    {
        if (is_array($data)) {
            $set = array();
            foreach ($data AS $k => $value) {
                $set[] = $k . "='" . $this->setQuote($value) . "'";
            }
            if (sizeof($this->setArray) > 0) {
                $this->set = " " . join(", ", $set) . ", " . join(",", $this->setArray);
            } else {
                $this->set = " " . join(", ", $set);
            }
        } else {
            if (sizeof($this->setArray) > 0) {
                $this->set = join(",", $this->setArray);
            } else {
                $this->set = "";
            }
        }
        return $this;
    }
    /**
     *
     * 执行更新操作
     * @param $table
     * @return Int 返回影响的行数
     */
    final function updateRows($table)
    {
        $this->modelSQL = $sql = sprintf($this->_query['UPDATE'], $table) . $this->set . $this->where . $this->limit;
        $this->cleanData();
        return $this->exec($sql);
    }

    /**
     *
     * 执行删除操作
     * @param String $table
     */
    final function deleteRows($table)
    {
        $this->modelSQL = $sql = sprintf($this->_query['DELETE'], $table, $this->where) . $this->limit;
        $this->cleanData();
        return $this->exec($sql);
    }

    /**
     * 执行Model过程中保存的相关信息
     *
     * @param String $option
     * @return Mix
     */
    final function querySQL($option = '')
    {
        $allow = array('_queryTimes', '_querySeconds', '_errorInfo', '_exeSQL');
        if (in_array($option, $allow)) {
            return $this->{$option};
        }
        return 0;
    }

    /**
     * 将结果编码一下
     * @param String $word
     * @return String|multitype:
     */
    public function setQuote($word)//过滤sql字符
    {
        if (ini_get("magic_quotes_gpc")) {
            return $word;
        }
        return is_array($word) ? array_map('addslashes', $word) : addslashes($word);
    }

    /**
     * 获取错误码
     */
    public function getCode()
    {
        return $this->response->getCode();
    }

    /**
     * 获取错误信息
     */
    public function getMessage()
    {
        if ($this->response->isError()) {
            return $this->response->getMessage();
        }
    }

    /**
     * 返回response对象
     *
     * @return Bool
     */
    public function getResponse()
    {
        return $this->response;
    }

    /**
     * 转换字符创
     *
     * @param $str
     * @return array|string
     */
    public function iconv($str)
    {
        if (is_array($str)) {
            return array_map(function ($n) {
                return toUtf8($n);
            }, $str);
        }
        return toUtf8($str);
    }

    /**
     * 如果不存在指定的方法则调用提示错误
     *
     * @param String $name
     * @param Mix $args
     * @return Mix
     */
    public function __call($method, $argvs)
    {
        if (isset($this->_modelAlias[$method])) {
            if (method_exists($this, $this->_modelAlias[$method])) {
                return call_user_func_array(array($this, $this->_modelAlias[$method]), $argvs);
            }
            \Qii::setError(false, __LINE__, 1506, 'Alias ' . get_called_class() . '->' . $method . '()');
        }
        \Qii::setError(false, __LINE__, 1506, get_called_class() . '->' . $method . '()');
    }
}