<?php
namespace Qii\Driver\Traits;

use admin\api\office\actions\lists;
use Qii\Exceptions\InvalidParams;
use Qii\Exceptions\TableException;

const JOINTYPE = [
    'LEFTJOIN' => 'LEFT JOIN',
    'RIGHTJOIN' => 'RIGHT JOIN',
    'INNERJOIN' => 'INNER JOIN',
    'OUTERJOIN' => 'OUTER JOIN',
    'FULLOUTERJOIN' => 'FULL OUTER JOIN',
    'LEFTOUTERJOIN' => 'LEFT OUTER JOIN',
    'RIGHTOUTERJOIN' => 'RIGHT OUTER JOIN'
];
trait SQL
{

    private $operator = ['and', 'or'];
    /**
     * sql
     * @var string[]
     */
    private $query = array(
        "INSERT" => "INSERT INTO %s(%s) VALUES(%s)",
        "REPLACE" => "REPLACE INTO %s (%s) VALUES(%s)",
        "SELECT" => "SELECT %s FROM %s %s",
        "UPDATE" => "UPDATE %s SET %s",
        "DELETE" => "DELETE FROM %s %s",
        "WHERE" => " WHERE %s",
        "OR" => " `%s` = '%s' ",
        "ORDER" => " ORDER BY %s",
        "GROUP" => " GROUP BY %s",
        "LIMIT" => " LIMIT %d, %d",
        "HAVING" => " HAVING %s",
        "BETWEEN" => " BETWEEN %s AND %s",
    );
    private $condition = ['eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'in', 'between', 'like', 'llike', 'rlike'];
    private $conditionFormatter = [
        'eq' => "%s = '%s'",
        'neq' => "%s != '%s'",
        'gt' => "%s > '%s'",
        'lt' => "%s < '%s'",
        'gte' => "%s >= '%s'",
        'lte' => "%s <= '%s'",
        'in' => "%s IN (%s)",
        'between' => "%s BETWEEN %s AND %s",
        'like' => "%s LIKE '%%%s%%'",
        'llike' => "%s LIKE '%%%s'",
        'rlike' => "%s LIKE '%s%%'",
    ];
    /**
     * sql执行的时间
     *
     * @var array
     */
    private $timer = [];
    /**
     * 执行的sql语句
     * @var array
     */
    private $sql = [];

    /**
     * 查询字段
     * @var array|string $fields
     */
    private $fields = null;
    /**
     * join
     * @var string|null string
     */
    private $join = null;

    /**
     * where
     * @var string | null $where
     */
    private $where = null;

    /**
     * group by
     * @var string|null $group
     */
    private $group = null;
    /**
     * order
     * @var string|null $order
     */
    private $order = null;
    /**
     * having
     * @var string|null
     */
    private $having = null;

    private $limit = null;

    private $sets = null;
    /**
     * 查询的表名
     *
     * @var null $table 表名
     */
    private $table = null;
    /**
     * 执行的SQL及耗时
     *
     * @var array [{sql:'xxx', start:1723232121.111, end: 1723232121.112, cost:0.001}]
     */
    private $executionSQL = [];

    final public function clean(){
        $this->sql = [];
        $this->fields = null;
        $this->join = null;
        $this->where = null;
        $this->group = null;
        $this->order = null;
        $this->having = null;
        $this->limit = null;
        $this->sets = null;
        $this->table = null;
    }

    /**
     * 查询字段
     *
     * @param mixed $fields
     * @return $this
     */
    final public function fields($fields) {
        if(!is_string($fields) && !is_array($fields)) {
            return $this;
        }
        if($fields == '*') {
            $this->fields = null;
        }

        if(!is_array($fields)) {
            if(preg_match('/(COUNT|SUM)\((.*)\)/', $fields)) {
                $this->fields = $fields;
                return $this;
            }
            // 如果是统计SQL，就只要统计相关字段
            $this->fields = $this->fields == null ? $fields : $this->fields . ', ' . $fields;
            return $this;
        }

        if(preg_match('/(COUNT|SUM)\((.*)\)/', $this->fields)) {
            return $this;
        }
        $arr = [];
        foreach($fields as $field) {
            // 处理 ['table1.field', 'table2.field']
            $tmp = explode('.', $field);
            if(count($tmp) == 2) {
                if($tmp[1] == '*') {
                    $arr[] = $tmp[0]. '.'.$tmp[1];
                }else{
                    $arr[] = $tmp[0]. '.'. $this->handleSelectFieldName($tmp[1]);
                }
            }else{
                if($field == '*'){
                    $arr[] = $field;
                }else{
                    $arr[] = $this->handleSelectFieldName($field);
                }
            }
        }
        $this->fields = $this->fields != null ? $this->fields .' , '. join(', ',$arr) : join(' , ',$arr);
        return $this;
    }

    /**
     * 处理查询字段
     *
     * @param string $field 字段名
     * @return mixed|string
     */
    protected function handleSelectFieldName($field){
        if(stristr($field, 'as') !== false) {
            return $field;
        }
        return '`'.trim($field).'`';
    }

    /**
     * sql执行的开始时间
     *
     * @param string $sql 执行的sql
     * @return void
     */
    final public function startTime($sql){
        $this->executionSQL[] = [
            'sql' => $sql,
            'start' => microtime(true)
        ];
    }

    /**
     * sql执行结束记录结束时间
     *
     * @param $sql
     * @return void
     */
    final public function endTime($sql) {
        $sqls = array_column($this->executionSQL, 'sql');
        $index = array_search($sql, $sqls);
        if($index === false) {
            return;
        }
        $item = $this->executionSQL[$index];
        $item['end'] = microtime(true);
        $item['cost'] = sprintf('%.04f', $item['end'] - $item['start']) ;
        $this->executionSQL[$index] = $item;
    }

    /**
     * 过滤值
     *
     * @param string|array $word
     * @return array|string
     * @throws InvalidParams
     */
    final function setQuote($word)
    {
        if (ini_get("magic_quotes_gpc")) {
            return $word;
        }
        $this->handleError(in_array(gettype($word), array("object", "resource","resource (closed)")), '期待参数为数组或字符串，获取到的是:'. gettype($word)."(". json_encode($word) .")");
        return is_array($word) ? array_map('addslashes', $word) : addslashes($word);
    }

    /**
     * 处理 table.field 这种形式的字段
     *
     * @param string $field 字段名
     * @return mixed|string
     */
    private function handleFieldAlias($field) {
        if(!stristr($field, '.')) {
            if(!stristr($field, '`')) {
                return '`' . $field. '`';
            }
            return $field;
        }
        $tmp = explode('.', $field);
        if(count($tmp) != 2) {
            return $field;
        }
        return $tmp[0] . '.`' . $tmp[1] . '`';
    }

    /**
     * 处理字段及值 field1:field2:field2:field4:eq|neq|gt... val
     * field1 eq val or field2 eq val ....
     * @param $field
     * @param $val
     * @return string
     * @throws \Exception
     */
    private function handleWhereField($field, $val) {
        $this->handleError(!$field, '字段名不能为空');
        $tmp = explode(':', $field);
        if(count($tmp) == 1) {
            return sprintf($this->conditionFormatter['eq'], $this->handleFieldAlias($field), $this->setQuote($val));
        }
        $cond = array_pop($tmp);
        if(!in_array($cond, $this->condition)) {
            $tmp[] = $cond;
            $cond = 'eq';
        }
        $arr = [];
        foreach($tmp as $v) {
            $cond = strtolower($cond);
            if(!isset($this->conditionFormatter[$cond])) {
                continue;
            }
            $this->handleError($cond == 'between' && !is_array($val), 'BETWEEN的值必须为数组格式[a,b]');
            if($cond == 'between') {
                $arr[] = sprintf($this->conditionFormatter[$cond], $this->handleFieldAlias($v), "'". $this->setQuote($val[0]) . "'", "'". $this->setQuote($val[1]) ."'");
                continue;
            }
            if($cond == 'in' && is_array($val)) {
                $arr[] = sprintf($this->conditionFormatter[$cond], $this->handleFieldAlias($v), "'". join("', '", $this->setQuote($val)) . "'");
                continue;
            }
            if(is_array($val)) {
                throw new \Exception('eq|neq|gt|gte|lt|lte|like值不能为数组');
            }
            $arr[] = sprintf($this->conditionFormatter[$cond], $this->handleFieldAlias($v), $this->setQuote($val));
        }
        return '('. join(' OR ', $arr) . ')';
    }

    /**
     * @param $where
     * @return mixed
     * @throws \Exception
     */
    private function handleSubWhere($where) {
        $arr = [];

        $count = count($where);
        // 多维数组处理
        if(count($where, 1) > $count) {
            foreach($where as $k => $v) {
                if(is_numeric($k) && is_array($v)) {
                    $arr[] = "(". join(" ", $this->handleSubWhere($v)) . ")";
                    $arr[] = 'AND';
                    continue;
                }
                if(is_numeric($k) && is_string($v) && in_array(strtolower($v), $this->operator)) {
                    if(in_array(strtolower($arr[count($arr) - 1]), $this->operator)) {
                        $arr[count($arr) - 1] = strtoupper($v);
                        continue;
                    }
                    $arr[] = strtoupper($v);
                    continue;
                }
                $arr[]  = $this->handleWhereField($k, $v);
                $arr[] = 'AND';
            }
            if($arr[count($arr) - 1] == 'AND') {
                array_pop($arr);
            }
            return $arr;
        }

        $lastIsOperator = false;
        foreach($where as $key => $val) {
            if(is_numeric($key) && is_string($val) && in_array(strtolower($val), $this->operator)) {
                $arr[] = strtoupper($val);
                $lastIsOperator = true;
                continue;
            }
            if(!$lastIsOperator && count($arr) > 0) {
                $arr[] = 'AND';
            }
            $lastIsOperator = false;
            $arr[] = $this->handleWhereField($key, $val);
        }
        return $arr;
    }

    /**
     * 支持复杂的where条件
     * field1 = '' and field2= ''
     * ['field1' => '', 'field2' => '']
     * ['field1' => '', 'and', 'field2' => '']
     * ['field1'  => '', 'or', 'field2' => ''] ['field3' => '']
     * [['field1'  => '', 'and', 'field2' => ''], 'or', ['field3' => '']]
     *
     * 当同时执行 where()->or() 的时候 where条件会整个括起来, 再通过or与or()相连
     *
     * 数组中field 支持
     * ['field1:eq|ueq|like|gt|gte|lt|lte|between|in' => val]
     * ['field1:field2|field3...:eq|neq|like|gt|gte|lt|lte|between|in' => val] 多字段or的形式
     *
     * @param string|array $where
     * @return $this
     * @throws InvalidParams
     */
    final public function where($where) {
        $this->handleError(!is_array($where) && !is_string($where), '查询条件不能必须为字符串或数组');
        if(!is_array($where)) {
            $this->where = $this->where != null ? ($this->where) . ' AND '. $where : $where;
            return $this;
        }
        if(count($where) == 0) {
            return $this;
        }
        $arr = $this->handleSubWhere($where);
        $sub = '('. join(' ', $arr) . ')';
        $this->where = $this->where != null ? $this->where . ' AND '. $sub : $sub;
        return $this;
    }

    /**
     * or 条件
     * @param $or
     * @return $this
     * @throws \Exception
     */
    final public function or($or){
        if(!$or)  {
            return $this;
        }
        if(is_string($or)) {
            $this->where = $this->where != null ? $this->where . ' OR ('. $or . ')' : $or;
            return $this;
        }
        $arr = $this->handleSubWhere($or);
        $sub = '('. join(' ', $arr) . ')';
        $this->where = $this->where != null ? '('. $this->where . ') OR '. $sub : $sub;
        return $this;
    }

    /**
     * @param $and
     * @return $this
     */
    final public function and($and){
        return $this->where($and);
    }

    /**
     * like %keyword%
     * @param $like
     * @param string $type like/llike/rlike
     * @return $this
     * @throws InvalidParams
     */
    final public function like($like, $type = 'like'){
        $this->handleError(!in_array($type, array('like', 'llike', 'rlike')), 'LIKE 只接受like/llike/rlike');
        if(!is_array($like)) {
            $this->where = $this->where != null ? '('. $this->where . ') AND '. $like : $like;
        }
        $arr = [];
        foreach($like as $key => $val) {
            $arr[$key .':'. $type] = $val;
        }

        return $this->where($arr);
    }

    /**
     * llike %keyword
     * @param $like
     * @return $this
     * @throws InvalidParams
     */
    final public function llike($like){
        return $this->like($like, 'llike');
    }

    /**
     * rlike %keyword
     * @param $like
     * @return $this
     * @throws InvalidParams
     */
    final public function rlike($like){
        return $this->like($like, 'rlike');
    }

    /**
     * @param $group
     * @return $this
     */
    final public function group($group){
        $this->handleError(!is_array($group) && !is_string($group), 'group by 参数必须为字符串或数组');
        if(is_string($group)) {
            $this->group = $this->group != null ? $this->group . ', '. $group : sprintf($this->query['GROUP'], $group);
            return $this;
        }
        if(count($group) == 0) {
            return $this;
        }
        $this->group = $this->group != null ? $this->group . ', '. join(", ", $group) : sprintf($this->query['GROUP'], join(", ", $group));
        return $this;
    }

    /**
     * @param $order
     * @return $this
     */
    final public function order($order){
        $this->handleError(!is_array($order) && !is_string($order), 'order 参数必须为字符串或数组, 获取到的是'. gettype($order));

        if((is_array($order) && count($order) == 0) || preg_match('/(COUNT|SUM)\((.*)\)/', $this->fields)) {
            return $this;
        }

        if(is_string($order)) {
            $this->order = $this->order == null ? sprintf($this->query['ORDER'], $order) : $this->order . ','. $order;
            return $this;
        }
        $arr = [];
        foreach($order as $key => $val) {
            $arr[] = $key .' '. $val;
        }
        $this->order = $this->order == null ? sprintf($this->query['ORDER'], join( ',', $arr)) : $this->order . ', '. join( ',', $arr);
        return $this;
    }
    /**
     * @param $table
     * @param string|array $on
     * @param string $joinType LEFT JOIN / RIGHT JOIN / INNER JOIN
     * @return $this
     */
    final public function join($table, $on, $joinType = JOINTYPE['LEFTJOIN']){
        $arr = [];
        if(!in_array($joinType, [
            JOINTYPE['LEFTJOIN'],
            JOINTYPE['RIGHTJOIN'],
            JOINTYPE['INNERJOIN'],
            JOINTYPE['OUTERJOIN'],
            JOINTYPE['FULLOUTERJOIN'],
            JOINTYPE['LEFTOUTERJOIN'],
            JOINTYPE['RIGHTOUTERJOIN']
        ]))
        if(is_array($on)) {
            foreach($on as $key => $val) {
                $arr[] = $key .' = '. $val;
            }
            $on = join(' AND ', $arr);
        }
        $this->join = $this->join . PHP_EOL . $joinType  .' '. $table .' ON '. $on;
        return $this;
    }

    /**
     * right join
     * @param string $table 表名
     * @param array $on on条件
     * @return $this
     */
    final public function rightJoin($table, $on) {
        return $this->join($table, $on, JOINTYPE['RIGHTJOIN']);
    }

    /**
     * right join
     * @param string $table 表名
     * @param array $on on条件
     * @return $this
     */
    final public function innerJoin($table, $on) {
        return $this->join($table, $on, JOINTYPE['INNERJOIN']);
    }

    /**
     * @param $having
     * @return $this
     */
    final public function having($having){
        if($having != null){
            $this->having = sprintf($this->query['HAVING'], $having);
        }
        return $this;
    }

    /**
     * @param int $start start
     * @param int|null $limit limit
     * @return $this
     */
    final public function limit($start, $limit = null){
        if($limit == null){
            $limit = $start;
            $start = 0;
        }
        $this->limit =  sprintf($this->query['LIMIT'], $start, $limit);
        return $this;
    }

    /**
     * @param $offset
     * @return $this
     */
    final public function offset($offset){
        return $this->limit($offset);
    }

    /**
     * 查询
     * @param string $table 表名，如果为空则从from中取
     * @return string
     * @throws TableException
     */
    final public function selectSQL($table = null){
        if($table == null) {
            $table = $this->table;
        }
        $this->handleError(!$this->verifyTable($table), '表名格式不正确');
        $sql = sprintf(
            $this->query['SELECT'],
            ($this->fields != null ? $this->fields : '*'),
            $table,
            $this->montage(
                $this->join,
                ($this->where != null ? sprintf($this->query['WHERE'], $this->where) : ''),
                $this->group,
                $this->having,
                $this->order,
                $this->limit
            )
        );
        $this->executeSQL = $sql;
        $this->clean();
        return $sql;
    }

    /**
     * 保存数据
     * @param string $table 表名
     * @param array $data 数据
     * @param string $opt INSERT/REPLACE
     * @return string
     * @throws InvalidParams
     */
    protected function createData($table, $data, $opt = 'INSERT') {
        $this->handleError(!isset($this->query[$opt]), '不支持的操作方法');
        if(is_object($data)) {
            $data = get_object_vars($data);
        }
        if($table == null) {
            $table = $this->table;
        }
        $this->handleError(!$this->verifyTable($table) || !$data, 'insert参数必须包含表名及插入的数据');

        $fields = [];
        $value = [];
        foreach($data as $field => $val) {
            $fields[] = '`'. $field .'`';
            if(strtolower(gettype($val)) == 'null') {
                $value[] = 'null';
                continue;
            }
            $value[] = "'". $this->setQuote($val) ."'";
        }
        $sql = sprintf($this->query[$opt], $table, join(', ', $fields), join(', ', $value));
        $this->executeSQL = $sql;
        return $sql;
    }
    /**
     * insert into table
     * @param string $table 表名
     * @param array $data 数据 可以为array 或者 new \stdClass()
     * @return string
     * @throws InvalidParams
     */
    final public function insertSQL($table = null, $data = []){
        return $this->createData($table, $data, 'INSERT');
    }

    /**
     * replace into table
     * @param string $table 表名
     * @param array $data 数据
     * @return string
     * @throws InvalidParams
     */
    final public function replaceSQL($table = null, $data = []){
        return $this->createData($table, $data, 'REPLACE');
    }

    /**
     * sets 更新数据使用
     * @param $data
     * @return $this
     * @throws InvalidParams
     */
    final public function sets($data) {
        $this->handleError(!is_array($data) && !is_string($data), '参数必须为字符串或数组');
        if(is_string($data)) {
            $this->sets = $this->sets == null ? $data : $this->sets . ', '. $data;
            return $this;
        }
        foreach ($data as $field => $val) {
            $this->set($field, $val);
        }
        return $this;
    }

    /**
     * set 单个更新数据使用
     * @param $field
     * @param $value
     * @return $this
     * @throws InvalidParams
     */
    final public function set($field, $value = null){
        if(is_array($field)) {
            foreach ($field as $k => $v) {
                $this->set($k, $v);
            }
            return $this;
        }
        $this->handleError(!is_string($field), '字段名必须为字符串，获取到的为'. print_r($field, true));
        // 如果有 incr decr
        if(strlen($field) > 5 && strpos($field, ':') !== false) {
            $opt = substr($field, strpos($field, ':'));
            if(in_array($opt, array(':incr', ':decr', ':plus', ':minus'))) {
                $field = $this->formatField(substr($field, 0, -5));
                if(in_array($opt,  array(':incr', ':plus'))) {
                    $val = $this->handleFieldAlias($field) .'='. $this->handleFieldAlias($field) .'+'. $value;
                }else{
                    $val = $this->handleFieldAlias($field) .'='. $this->handleFieldAlias($field) .'-'. $value;
                }
                $this->sets = $this->sets != null ? $this->sets . ', '. $val : $val;
                return $this;
            }
        }
        $val = $this->handleFieldAlias($field) ."='". $this->setQuote($value) . "'";
        $this->sets = $this->sets != null ? $this->sets . ', '. $val : $val;
        return $this;
    }

    /**
     * 增加某一个字段值
     * @param string $field 字段名
     * @param int|float $val
     * @return $this
     * @throws InvalidParams
     */
    final public function incr($field, $val){
        return $this->set($field . ':incr', $val);
    }

    /**
     * 减小某一个字段值
     * @param string $field 字段名
     * @param int|float $val
     * @return $this
     * @throws InvalidParams
     */
    final public function decr($field, $val) {
        return $this->set($field . ':decr', $val);
    }
    /**
     * 更新数据
     *
     * @param string $table
     * @return string
     * @throws InvalidParams
     */
    final public function updateSQL($table = null){
        if($table == null){
            $table = $this->table;
        }
        $this->handleError(!$this->verifyTable($table), '数据表格式不正确');
        $sql = sprintf(
            $this->query['UPDATE'],
            $table,
            $this->montage(
                $this->sets,
                ($this->where != null ? sprintf($this->query['WHERE'], $this->where) : ''),
                $this->formatLimitForUpdate($this->limit)
            )
        );
        $this->executeSQL = $sql;
        $this->clean();
        return $sql;
    }

    /**
     * 删除数据
     * @param string $table 表名
     * @return string
     * @throws InvalidParams
     */
    final public function deleteSQL($table = null){
        if($table == null){
            $table = $this->table;
        }
        $this->handleError(!$this->verifyTable($table), '数据表格式不正确');

        $sql = sprintf($this->query['DELETE'], $table, $this->montage(
            ($this->where != null ? sprintf($this->query['WHERE'], $this->where) : ''),
            $this->formatLimitForUpdate($this->limit)
        ));
        $this->executeSQL = $sql;
        $this->clean();
        return $sql;
    }

    /**
     * 去掉null的值，并将他们拼接在一起
     *
     * @return string
     */
    protected function montage(){
        $arr = func_get_args();
        $tmp = [];
        foreach ($arr as $value) {
            if($value !== null) {
                $tmp[] = $value;
            }
        }
        return join(PHP_EOL, $tmp);
    }

    /**
     * from table
     * @param string $table 表名
     * @return $this
     * @throws InvalidParams
     */
    final public function from($table){
        $this->handleError(!$table, '查询表名');
        $this->handleError(!$this->verifyTable($table), '数据表格式');
        $this->table = $table;
        return $this;
    }

    /**
     * 如果$bool为true直接抛出异常
     *
     * @param bool $bool bool
     * @param string $msg 异常提示消息
     * @return false
     * @throws InvalidParams
     */
    final public function handleError($bool, $msg) {
        if($bool) {
            throw new InvalidParams(_i('%s is invalid', $msg), 400);
        }
        return false;
    }
    /**
     * 验证数据表名是否符合规范
     * 表名不能以数字开头，
     *
     * @param string $name
     * @return bool
     */
    final public function verifyTable($name) {
        if (!is_string($name) || (
                // table
                !preg_match("/^[a-zA-Z_]+[a-zA-Z0-9_]{0,}$/", $name) &&
                // `table`
                !preg_match("/^`[a-zA-Z_]+[a-zA-Z0-9_]{0,}`$/", $name)) &&
            // table alias
            !preg_match("/^[a-zA-Z_]+[a-zA-Z0-9_]{0,}\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
            // `table` alias
            !preg_match("/^`[a-zA-Z_]+[a-zA-Z0-9_]{0,}`\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
            // database.table
            !preg_match("/^[a-zA-Z]+\.[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name) &&
            !preg_match("/^[a-zA-Z]+\.[a-zA-Z]+[a-zA-Z0-9_]{0,}\s+[a-zA-Z]+[a-zA-Z0-9_]{0,}$/", $name)
        ) {
            return false;
        }
        return true;
    }


    /**
     * 获取表的别名
     *
     * @param string $name 名字
     * @return array
     */
    final protected function getTableAlias($name)
    {
        if (!$this->verifyTable($name)) {
            if (gettype($name) == 'string') {
                throw new TableException("表名不能包含怪字符且不能以数字开头，获取到的是". $name);
            }
            throw new TableException("表名必须是字符串加下划线,目标字符为". gettype($name));
        }
        //去掉table前后的``符号
        $name = str_replace('`', '', $name);
        $aliases = explode(' ', $name);
        //检查表名中时候含数据库名，有数据表名的时候需要单独处理
        $hasDatabaseName = false;
        if(stristr($name, '.')) {
            $hasDatabaseName = true;
        }
        if(count($aliases) == 1) {
            if($hasDatabaseName) {
                $names = explode(".", $name);
                $name = $names[0] . ".`". $names[1] . "`";
            }else{
                $name = "`". $name ."`";
            }
            return array('alias' => '', 'name' => $name);
        }
        $res = array();
        $res['alias'] = array_pop($aliases);
        $res['name'] = join(" ", array_slice($aliases, -1));
        if($hasDatabaseName) {
            $names = explode(".", $res['name']);
            $res['name'] = $names[0] . ".`". $names[1] . "`";
        }else{
            $res['name'] = "`". $res['name'] ."`";
        }
        return $res;
    }
    /**
     * UPDATE DELETE 仅支持 LIMIT count 方式
     *
     * @param string $limit LIMIT 1,10
     * @return mixed|string
     */
    final public function formatLimitForUpdate($limit) {
        preg_match("/LIMIT\s+(\d+),\s+(\d+)/", $limit, $matches);
        if(count($matches) == 3) {
            return "LIMIT ". intval($matches[2]);
        }
        return $limit;
    }

    /**
     * 格式化 a.field 格式为 a.`field`
     * @param string $field 字段名
     * @return mixed|string
     */
    final public function formatField($field) {
        if(strpos($field, '.') !== false) {
            preg_match("/^(.+)\.(.+)$/", $field, $matches);
            if(count($matches) == 3) {
                return $matches[1] . ".`". $matches[2] . "`";
            }
        }
        return $field;
    }

    /**
     * 返回所有执行的SQL及耗时
     *
     * @return array
     */
    final public function getExecutionSQL(){
        return $this->executionSQL;
    }
}