<?php

namespace Mall\Framework\Core;

use Mall\Framework\Factory;

abstract class SqlHelper
{
    const FETCH_ASSOC = \PDO::FETCH_ASSOC;
    const FETCH_OBJ = \PDO::FETCH_OBJ;

    /**
     * 数据库连接
     *
     * @var db
     */
    protected $db;

    /**
     * 数据库名称
     *
     * @var string
     */
    protected $_table = null;

    /**
     * 数据库查询主键
     *
     * @var string
     */
    protected $_primary = null;

    /**
     * 数据表字段
     *
     * @var array
     */
    protected $_fields = array();

    /**
     * 只读字段
     *
     * @var array
     */
    protected $_readonly = array();

    /**
     * 自动填充字段定义
     *
     * @var array
     */
    protected $_create_autofill = array();

    /**
     * 自动更新字段定义
     *
     * @var array
     */
    protected $_update_autofill = array();

    /**
     * 自动过滤字段定义
     *
     * @var array
     */
    protected $_filters_input = array();

    /**
     * 自动过滤字段定义
     *
     * @var array
     */
    protected $_filters_output = array();

    /**
     * 插入时，字段验证定义
     *
     * @var array
     */
    protected $_validators = array();

    /**
     * 插入时，准备好的数据
     *
     * @var array
     */
    protected $_data = array();

    /**
     * select 查询join where limit 等定义
     *
     * @var array
     */
    protected $_options = array();

    /**
     * 数据获取方式
     *
     * @var int
     */
    protected $_fetch_style = self::FETCH_ASSOC;

    /**
     * 用户ID
     *
     * @var int
     */
    public $_userid = null;

    /**
     * 用户名称
     *
     * @var string
     */
    public $_username = null;

    /**
     * 用户组ID
     *
     * @var int
     */
    public $_groupid = null;

    /**
     * 用户角色ID
     *
     * @var int
     */
    public $_roleid = null;

    /**
     * 错误信息
     *
     * @var mixed
     */
    public $error = null;

    /**
     * mysql 操作符
     * @var array
     */
    public static $operator = ['=','!=','>=','<=','like','in','>','<'];

    /**
     * 初始化数据库，用户定义
     *
     */
    function __construct($serviceDB)
    {
        $this->db = Factory::db($serviceDB);

        // 表前缀自动拼接
        $tablePrefix = $this->db->prefix();
        if( !empty($tablePrefix) ){
            $this->_table = $tablePrefix .'_'.$this->_table;
        }
    }

    public function __set($name, $value)
    {
        $this->_data[$name] = $value;
    }

    public function __get($name)
    {
        return isset($this->_data[$name]) ? $this->_data[$name] : null;
    }

    public function __isset($name)
    {
        return isset($this->_data[$name]);
    }

    public function __unset($name)
    {
        unset($this->_data[$name]);
    }

    public function __call($method, $args)
    {
        if (in_array($method, array('field', 'where', 'order', 'limit', 'offset', 'having', 'group', 'distinct', 'data'), true)) {
            $this->_options[$method] = $args[0];
            return $this;
        } elseif (in_array($method, array('sum', 'min', 'max', 'avg'), true)) {
            $field = isset($args[0]) ? $args[0] : '*';
            return $this->get_field($method . '(' . $field . ') AS `count`');
        } elseif (preg_match("/^(get|gets|delete)_by_(.*)$/", $method, $matches)) {
            $field = $matches[2];
            if (in_array($field, $this->_fields, true)) {
                array_unshift($args, $field);
                return call_user_func_array(array($this, $matches[1] . '_by'), $args);
            }
        }
        return;
    }

    /**
     * 设置查询读取模式
     *
     * @param int $style
     */
    public function set_fetch_style($style)
    {
        $this->_fetch_style = $style;
    }

    /**
     * 查询数据
     *
     * @param string|array $where
     * @param string|array $fields
     * @param string|array $order
     * @param int $limit
     * @param int $offset
     * @param array $data
     * @param boolean $multiple
     * @return array|boolean
     */
    function select($where = null, $fields = '*', $order = null, $limit = null, $offset = null, $data = array(), $multiple = true, $isExport = false , $join = null)
    {
        $having = $group = NULL;
        if (!empty($this->_options)) {
            $fields = isset($this->_options['field']) ? $this->_options['field'] : $fields;
            $fields = isset($this->_options['distinct']) ? "distinct " . $this->_options['distinct'] : $fields;
            $where = isset($this->_options['where']) ? $this->_options['where'] : $where;
            $having = isset($this->_options['having']) ? $this->_options['having'] : null;
            $order = isset($this->_options['order']) ? $this->_options['order'] : $order;
            $group = isset($this->_options['group']) ? $this->_options['group'] : null;
            $limit = isset($this->_options['limit']) ? $this->_options['limit'] : $limit;
            $offset = isset($this->_options['offset']) ? $this->_options['offset'] : $offset;
            $this->_options = array();
        }
        if (is_array($fields)) $fields = '`' . implode('`,`', $fields) . '`';
        $where = $this->_where($where);
        if($where === false){
            return false;
        }
        if (!$this->_before_select($where)) return false;
        if ($join){
            $sql = "SELECT $fields FROM `$this->_table` as a ".$join;
        }else{
            $sql = "SELECT $fields FROM `$this->_table` ";
        }

        if ($where && is_string($where)) $sql .= " WHERE $where ";
        if ($order) $sql .= " ORDER BY $order ";
        if ($group) $sql .= " GROUP BY $group ";
        if ($having) $sql .= " HAVING $having ";
        if (is_null($limit) && !$multiple) $sql .= " LIMIT 1 ";
        $method = $multiple ? 'select' : 'get';
        if($isExport){
            $method = 'exportSelect';
        }
//         var_dump($sql);
        $result = is_null($limit)
            ? $this->db->$method($sql, $data, $this->_fetch_style)
            : $this->db->limit($sql, $limit, $offset, $data, $this->_fetch_style);
        if ($result === false || empty($result)) {
            if ($this->db->error() && $this->db->errno() != '00000') {
                $this->error = $this->db->error();
                return false;
            }

            return [];
        } else {
            $this->_data = $result;
            $this->_after_select($result, $multiple);
            return $result;
        }
    }

    /**
     * 查询前执行
     *
     * @param array|string $where
     * @return boolean
     */
    protected function _before_select(&$where)
    {
        return true;
    }

    /**
     * 查询后执行
     *
     * @param array $result 查询后的结果
     * @param boolean $multiple 是否多条数据
     */
    protected function _after_select(&$result, $multiple = true)
    {
    }

    /**
     * 分页查询
     *
     * @param array|string $where
     * @param array|string $fields
     * @param string $order
     * @param int $page
     * @param int $size
     * @param array $data
     * @return array
     */
    public function page($where = null, $fields = '*', $order = null, $page = 1, $size = 20, $data = array())
    {
        $offset = ($page - 1) * $size;
        return $this->select($where, $fields, $order, $size, $offset, $data, true);
    }

    /**
     * 获得单条数据
     *
     * @param array|string $where
     * @param array|string $fields
     * @param string $order
     * @return array
     */
    public function get($where = null, $fields = '*', $order = null)
    {
        return $this->select($where, $fields, $order, null, null, array(), false);
    }

    /**
     * 根据字段值获得单条数据
     *
     * @param string $field
     * @param mixed $value
     * @param array|string $fields
     * @param string $order
     * @return array
     */
    public function get_by($field, $value, $fields = '*', $order = null)
    {
        return $this->select("`$field`=?", $fields, $order, null, null, array($value), false);
    }

    /**
     * 根据字段值查询多条数据
     *
     * @param string $field
     * @param mixed $value
     * @param array|string $fields
     * @param string $order
     * @param int $limit
     * @param int $offset
     * @return array
     */
    public function gets_by($field, $value, $fields = '*', $order = null, $limit = null, $offset = 0)
    {
        return $this->select("`$field`=?", $fields, $order, $limit, $offset, array($value), true);
    }

    /**
     * 根据字段值查询多条数据
     *
     * @param string $field
     * @param mixed $value
     * @param array|string $fields
     * @param string $order
     * @param int $limit
     * @param int $offset
     * @return object
     */
    public function exportSelect($where = null, $fields = '*', $order = null, $limit = null, $value = [], $offset = 0)
    {
        return $this->select($where, $fields, $order, $limit, $offset, $value, true, true);
    }


    /**
     * 获取单条字段值
     *
     * @param string $field
     * @param array|string $where
     * @param array $data
     * @return mixed
     */
    public function get_field($field, $where = null, $data = array())
    {
        $r = $this->select($where, $field, null, null, null, $data, false);
        if(empty($r)){
            return $r;
        }
        return array_shift($r);
    }

    /**
     * 获取字段集合
     *
     * @param string $field
     * @param array|string $where
     * @param array $data
     * @return array
     */
    public function gets_field($field, $where = null, $data = array())
    {
        $result = array();
        $data = $this->select($where, $field, null, null, null, $data, true);
        foreach ($data as $r) {
            $result[] = array_shift($r);
        }
        return $result;
    }

    /**
     * 获取总数
     *
     * @param array|string $where
     * @param array $data
     * @return int
     */
    public function count($where = null, $data = array(), $join = null)
    {
        $where = $this->_where($where);
        if($where === false){
            return false;
        }
        if (!empty($where)) $where = " WHERE $where";
        if ($join){
            $sql = "SELECT count(*) as `count` FROM `$this->_table` as a $join $where";
        }else{
            $sql = "SELECT count(*) as `count` FROM `$this->_table` $where";
        }
//        var_dump($sql);
        $r = $this->db->get($sql, $data);
        return $r ? $r['count'] : false;
    }

    /**
     * 获取主健定义
     *
     * @return string
     */
    public function primary()
    {
        return isset($this->_primary) ? $this->_primary : $this->db->get_primary($this->_table);
    }

    /**
     * 是否存在符合条件的记录
     *
     * @param array|string $field
     * @param mixed $value
     * @return boolean
     */
    public function exists($field, $value)
    {
        return $this->db->get("SELECT `$field` FROM `$this->_table` WHERE `$field`=?", array($value)) ? true : false;
    }

    /**
     * 插入数据
     *
     * @param array $data
     * @param boolean $multiple 是否批量插入
     * @return int|boolean
     */
    protected function insert($data = array(), $multiple = false)
    {
        $this->_data($data);
        if (!$this->_before_insert($data)) return false;

        $this->_create_autofill($data, $multiple);

        if($multiple){
            foreach ($data as $key => $value){
                $insertData[] = array_values($value);
            }
            $id = $this->db->insert("INSERT INTO `$this->_table` (`" . implode('`,`', array_keys($data[0])) . "`) VALUES(" . implode(',', array_fill(0, count($data[0]), '?')) . ")", $insertData, $multiple);
        }else{
            $id = $this->db->insert("INSERT INTO `$this->_table` (`" . implode('`,`', array_keys($data)) . "`) VALUES(" . implode(',', array_fill(0, count($data), '?')) . ")", array_values($data), $multiple);
        }
        if ($id === false) {
            $this->error = $this->db->error();
            return $this->error;
        } else {
            $this->_after_insert($data);
            return $id;
        }
    }


    /**
     * 替换方式插入数据
     *
     * @param array $data
     * @return int|boolean
     */
    protected function replace($data = array(), $multiple = false)
    {
        $this->_data($data);

        if (!$this->_before_insert($data)) return false;

        $this->_create_autofill($data, $multiple);

        if($multiple){
            foreach ($data as $key => $value){
                $insertData[] = array_values($value);
            }

            $id = $this->db->insert("REPLACE INTO `$this->_table` (`" . implode('`,`', array_keys($data[0])) . "`) VALUES(" . implode(',', array_fill(0, count($data[0]), '?')) . ")", $insertData, $multiple);
        }else{
            $id = $this->db->insert("REPLACE INTO `$this->_table` (`" . implode('`,`', array_keys($data)) . "`) VALUES(" . implode(',', array_fill(0, count($data), '?')) . ")", array_values($data));
        }

        if ($id === false) {
            $this->error = $this->db->error();
            return false;
        } else {
            $this->_after_insert($data);
            return $id;
        }
    }

    /**
     * 插入之前执行
     *
     * @param array $data
     * @return boolean
     */
    protected function _before_insert(&$data)
    {
        return true;
    }

    /**
     * 插入之后执行
     *
     * @param array $data
     */
    protected function _after_insert(&$data)
    {
    }

    /**
     * 根据ID拷贝一份
     *
     * @param int $id
     * @param array $data
     * @return int/boolean
     */
    public function copy_by_id($id, $data = array())
    {
        $r = $this->db->get("SELECT * FROM `$this->_table` WHERE `$this->_primary`=?", array($id));
        if (!$r) return false;
        unset($r[$this->_primary]);
        if ($data) $r = array_merge($r, $data);
        return $this->insert($r);
    }

    /**
     * 更新
     *
     * @param array $data
     * @param array /string $where
     * @param int $limit
     * @param array /string $order
     * @return int/boolean
     */
    protected function update($data = array(), $where = null, $limit = null, $order = null)
    {

        if (!empty($this->_options)) {
            $where = isset($this->_options['where']) ? $this->_options['where'] : $where;
            $order = isset($this->_options['order']) ? $this->_options['order'] : $order;
            $limit = isset($this->_options['limit']) ? $this->_options['limit'] : $limit;
            $offset = isset($this->_options['offset']) ? $this->_options['offset'] : $offset;
            $this->_options = array();
        }

        $this->_data($data);

        $where = $this->_where($where);
        if($where === false){
            return false;
        }

        if (!$this->_before_update($data, $where)) return false;

        $this->_update_autofill($data);

        $this->_readonly($data);


        $sql = "UPDATE `$this->_table` SET `" . implode('`=?,`', array_keys($data)) . "`=?";
        if ($where) $sql .= " WHERE $where ";
        if ($order) $sql .= " ORDER BY $order ";
        if ($limit) $sql .= " LIMIT $limit ";
        
        $result = $this->db->update($sql, array_values($data));

        if ($result === FALSE) {
            $this->error = $this->db->error();
            return false;
        } else {
            $this->_after_update($data, $where);
            return $result;
        }
    }

    /**
 * query方法
 */
    protected function query($sql)
    {
        if(!empty($sql)){
            $result = $this->db->query($sql);
            if($result === false){
                $this->error = $this->db->error();
                return false;
            }else{
                return $result;
            }
        }else{
            $this->error = 'sql is null';
            return false;
        }
    }

    /**
     * query方法
     */
    protected function exportQuery($sql)
    {
        if(!empty($sql)){
            $result = $this->db->exportQuery($sql);
            if($result === false){
                $this->error = $this->db->error();
                return false;
            }else{
                return $result;
            }
        }else{
            $this->error = 'sql is null';
            return false;
        }
    }

    /**
     * 更新记录之前执行
     *
     * @param array $data
     * @param array|string $where
     * @return boolean
     */
    protected function _before_update(&$data, $where)
    {
        return true;
    }

    /**
     * 更新记录之后执行
     *
     * @param array $data
     * @param array|string $where
     */
    protected function _after_update(&$data, $where)
    {
    }

    /**
     * 更新一个字段值
     *
     * @param string $field
     * @param mixed $value
     * @param string /array $where
     * @return int/boolean
     */
    public function set_field($field, $value, $where = null)
    {
        return $this->update(array($field => $value), $where);
    }

    /**
     * 递增一个int字段值
     *
     * @param string $field
     * @param string /array $where
     * @param int $step
     * @param array $data
     * @return int/boolean
     */
    public function set_inc($field, $where = null, $step = 1, $data = array())
    {
        $where = $this->_where($where);
        if($where === false){
            return false;
        }
        if(empty($step)){
            $step = 0;
        }
        $sql = "UPDATE " .$this->_table." SET `$field`=IFNULL(`$field`,0)+".$step." WHERE $where";
        return $this->db->update($sql, $data);
    }

    /**
     * 递减一个int字段值
     *
     * @param string $field
     * @param array /string $where
     * @param int $step
     * @param array $data
     * @return int/boolean
     */
    public function set_dec($field, $where = null, $step = 1, $data = array())
    {
        $where = $this->_where($where);
        if($where === false){
            return false;
        }
        if(empty($step)){
            $step = 0;
        }
        $sql = "UPDATE ".$this->_table." SET `$field`=IFNULL(`$field`,0)-".$step." WHERE $where";
        return $this->db->update($sql, $data);
    }

    /**
     * 删除
     *
     * @param array /string $where
     * @param int $limit
     * @param array /string $order
     * @param array $data
     * @return int/boolean
     */
    protected function delete($where = null, $limit = null, $order = null, $data = array())
    {
        if (!empty($this->_options)) {
            $where = isset($this->_options['where']) ? $this->_options['where'] : $where;
            $order = isset($this->_options['order']) ? $this->_options['order'] : $order;
            $limit = isset($this->_options['limit']) ? $this->_options['limit'] : $limit;
            $offset = isset($this->_options['offset']) ? $this->_options['offset'] : $offset;
            $this->_options = array();
        }

        $where = $this->_where($where);
        if($where === false){
            return false;
        }

        if (!$this->_before_delete($where)) return false;

        $sql = "DELETE FROM `$this->_table`";
        $asql = $sql;
        if ($where) $sql .= " WHERE $where ";
        if ($limit) {
            if ($order) $sql .= " ORDER BY $order ";
            $sql .= " LIMIT $limit ";
        }
        if ($sql == $asql) {
            return false;
        }

        $result = $this->db->delete($sql, $data);
        if ($result === FALSE) {
            $this->error = $this->db->error();
            return false;
        } else {
            $this->_after_delete($where);
            return $result;
        }
    }

    /**
     * 删除前执行
     *
     * @param array|string $where
     * @return boolean
     */
    protected function _before_delete(&$where)
    {
        return true;
    }

    /**
     * 删除后执行
     *
     * @param array|string $where
     */
    protected function _after_delete(&$where)
    {
    }

    /**
     * 根据字段值查询
     *
     * @param string $field
     * @param mixed $value
     * @param int $limit
     * @param array|string $order
     * @return int|boolean
     */
    public function delete_by($field, $value, $limit = null, $order = null)
    {
        return $this->delete("`$field`=?", $limit, $order, array($value));
    }


    /**
     * 获得一个字段的类型
     *
     * @param string $field
     * @return string
     */
    protected function _fieldtype($field)
    {

        static $fields;
        if (is_null($fields) || !isset($fields[$this->_table])) {
            if ($data = $this->db->list_fields($this->_table)) {
                foreach ($data as $k => $v) {
                    $fields[$v['Field']] = $v;
                }
            }
        }
        return isset($fields[$field]) && isset($fields[$field]['Type']) ? $fields[$field]['Type'] : '';

    }


    private function _create_autofill(& $data, $multiple = false)
    {
        if (empty($this->_create_autofill)) return true;
        if($multiple){
            foreach ($this->_create_autofill as $field => $val) {
                foreach ($data as $key => $value){
                    if (!isset($data[$key][$field])) $data[$key][$field] = $val;
                }
            }
        }else{
            foreach ($this->_create_autofill as $field => $val) {
                if (!isset($data[$field])) $data[$field] = $val;
            }
        }
    }

    private function _update_autofill(& $data)
    {
        if (empty($this->_update_autofill)) return true;
        foreach ($this->_update_autofill as $field => $val) {
            if (!isset($data[$field])) $data[$field] = $val;
        }
    }

    private function _readonly(& $data)
    {
        if (empty($this->_readonly)) return true;
        foreach ($this->_readonly as $field => $val) {
            if (isset($data[$field])) unset($data[$field]);
        }
    }

    private function checkVaule($where){
        if(is_string($where)){
            return addslashes($where);
        }
        return $where;
    }


    private function _where(& $where)
    {
        if (empty($where) && isset($this->_data[$this->_primary])) $where = $this->_data[$this->_primary];
        if (empty($where)) return null;

        if (is_numeric($where)) {
            $where = "`$this->_primary`=$where";
        } elseif (is_array($where)) {
            $condition = array();
            foreach ($where as $key => $value){
                if($key === 0 && is_numeric($value)){
                    $where = array_map(array(__CLASS__,'checkVaule'), $where);
                    $ids = is_numeric($where[0]) ? implode(',', $where) : "'" . implode("','", $where) . "'";
                    $where = "`$this->_primary` IN($ids)";
                    break;
                }else{
                    if(is_numeric($key) && count($value) == 3){
//                        if(!in_array($value[0],$this->_fields)){
//                            $this->error = $value[0].'字段未被映射';
//                            return false;
//                        }

                        if(!in_array($value[1], self::$operator)){
                            $this->error = $value[1].'查询不支持';
                            return false;
                        }

                        if(is_array($value[2])){
                            $sqlIn = '';
                            $len = count($value[2]);
                            foreach ($value[2] as $k => $v){
                                if(!is_numeric($v)){
                                    $sqlIn .="'".$v."'";
                                }else{
                                    $sqlIn .= $v;
                                }

                                if($len >1 && $k+1 != $len){
                                    $sqlIn .= ',';
                                }
                            }
                            $condition[] = "`$value[0]` $value[1] (".$sqlIn.")";
                        }else{
                            if (strstr($value[0], '|')){
                                $str = explode('|', $value[0]);
                                $condition[] = "$str[0] $value[1] '".$this->checkVaule($value[2])."' OR "."$str[1] $value[1] '".$this->checkVaule($value[2])."'";
                            }else{
                                if ($value[1] == 'in'){
                                    $condition[] = "$value[0] $value[1] (".$this->checkVaule($value[2]).")";
                                }else{
                                    $condition[] = "$value[0] $value[1] '".$this->checkVaule($value[2])."'";
                                }
                            }
                        }
                        $condition;
                    }else{
                        $where = array_map(array(__CLASS__,'checkVaule'), $where);
//                        if (in_array($key, $this->_fields)) {
                            if(is_array($value)){
                                $sqlIn = '';
                                $len = count($value);
                                foreach ($value as $k => $v){
                                    if(!is_numeric($v)){
                                        $sqlIn .="'".$v."'";
                                    }else{
                                        $sqlIn .= $v;
                                    }

                                    if($len >1 && $k+1 != $len){
                                        $sqlIn .= ',';
                                    }
                                }
                                $condition[] = "$key in(".$sqlIn.")";
                            }else{
                                if (strstr($key, '|')){
                                    $str = explode('|', $key);
                                    $condition[] =  "$str[0] ='$value'"."' OR "."$str[0] ='$value'";
                                }else{
                                    $condition[] = "$key ='$value'";
                                }
                            }
//                        }else{
//                            $this->error = $key.'字段未被映射';
//                            return false;
//                        }
                    }
                }
            }
            if(!empty($condition)){
                $where = implode(' AND ', $condition);
            }
        } elseif (preg_match("/^[0-9a-z\'\"\,\s]+$/i", $where)) {
            $where = strpos($where, ',') === false ? "`$this->_primary`='$where'" : "`$this->_primary` IN($where)";
        }

        $notice_flags = array('select', 'delete', 'insert', 'drop', 'update', 'benchmark', 'database');
        $quote = strpos($where, '"') === true ? '"' : "'";
        foreach ($notice_flags as $w) {
            $where = preg_replace('#([\s\(\)\!])' . $w . '([\s\(\)\*])#i', "$1" . substr($w, 0, 1) . $quote . '/**/' . $quote . substr($w, 1) . "$2", $where);
        }
        return $where;
    }

    private function _data(& $data)
    {
        if (empty($data)) {
            if (!empty($this->_options['data'])) {
                $data = $this->_options['data'];
            } elseif (!empty($this->_data)) {
                $data = $this->_data;
            } elseif (!empty($_POST)) {
                $data = $_POST;
            }
        }
    }

    /**
     * 过滤不需要的字段
     *
     * @param array $data 输入数据
     * @param array $keys 需要的字段定义
     * @return array
     */
    protected function filter_array($data, $keys)
    {
        // 合并附加字段
        $fields = $this->_get_extra_fileds();
        if ($fields) {
            $fields = array_filter(array_keys($fields));
            if ($fields) {
                $keys = array_unique(array_merge($keys, $fields));
            }
        }

        foreach ($data as $field => $v) {
            if (!in_array($field, $keys)) unset($data[$field]);
        }
        return $data;
    }

    /**
     * 获取模型操作中的错误，并返回字符串类型的错误
     *
     * @return string
     */
    public function error()
    {
        $error = $this->error;
        if (empty($error)) {
            $error = $this->db->error();
        }
        if (empty($error)) {
            return '';
        } else {
            if (is_array($error)) {
                $error = implode("*****", $error);
            }
            return $error;
        }
    }

    /**
     * 切换分表
     * @param $tablename
     */
    public function get_Table()
    {
       return $this->_table;
    }


    /**
     * 切换分表
     * @param $tablename
     */
    public function set_Table($tablename)
    {
        $this->_table = $tablename;
    }

    /**
     * 开启事务
     * @param bool $foreign_key_checks
     * @return mixed
     */
    public function beginTransaction($foreign_key_checks = false)
    {
        return $this->db->beginTransaction($foreign_key_checks)?true:false;
    }

    /**
     * 提交事务
     * @return mixed
     */
    public function commit()
    {
        return $this->db->commit();
    }

    /**
     * 回滚事务
     * @return mixed
     */
    public function rollBack()
    {
        return $this->db->rollBack();
    }
}