<?php
/**
 * 表模型类
 * @copyright reginx.com
 * $Id: tab.class.php 199 2013-03-20 16:20:51Z reginx $
 */
class tab{
    /**
     * 表 DB 配置
     *
     * @var unknown_type
     */
    public $dbconf = array();

    /**
     * 表数据
     *
     * @var unknown_type
     */
    public $data = array();

    /**
     * 字段输入验证
     *
     * @var unknown_type
     */
    public $validate = array();

    /**
     * 字段默认
     *
     * @var unknown_type
     */
    public $default = array();

    /**
     * 字段过滤规则
     *
     * @var unknown_type
     */
    public $filter = array();

    /**
     * 数据验证错误信息
     *
     * @var unknown_type
     */
    private $_errmsg = array();

    /**
     * 数据库连接对象
     *
     * @var unknown_type
     */
    private $_dbobj = null;

    /**
     * sql语句构造数组
     *
     * @var unknown_type
     */
    private $_sql = array();

    /**
     * 表模型配置信息
     *
     * @var unknown_type
     */
    private $_conf = array();

    /**
     * 数据返回索引 默认为数字
     *
     * @var unknown_type
     */
    private $_rkey = null;

    /**
     * 是否保留上一次查询的条件
     *
     * @var unknown_type
     */
    private $_keep = FALSE;
    
    /**
     * 执行一次sql之后, 是否清空当前对象data
     * 生效次数一次
     *
     * @var unknown_type
     */
    private $_initdata = true; 

    /**
     * 构造函数
     * 支持单表定义配置
     */
    public function __construct($class = null, $dbconf = array()){
        $this->_dbobj = db_extra::getobj(empty($dbconf) ? $GLOBALS['_APP']['db'] : $dbconf);
        $this->_conf = $GLOBALS['_APP']['db'][$GLOBALS['_APP']['db']['class']][$this->_dbobj->serverid()];
        $class = empty($class) ? get_class($this) : $class;
        if($class != __CLASS__){
            $this->_conf['table'] = substr($class, 0, -4);
            $this->_conf['table_name'] = '`' . $this->_conf['pre'] . $this->_conf['table'] . '`';
            $this->_initab();
        }
    }

    /**
     * 设置 _initdata
     *
     * @param unknown_type $bool
     */
    public function initdata($bool=false){
        $this->_initdata = (bool)$bool;
        return $this;
    }
    
    /**
     * 获取表结构
     */
    private function _initab(){
        $this->_conf['fields'] = $GLOBALS['_CACHE']->get('REGINX@' . $this->_conf['table'] . '_struct', '');
        if(!$this->_conf['fields']){
            $this->_conf['fields'] = $this->_dbobj->getfields($this->_conf['table_name']);
            $GLOBALS['_CACHE']->set('REGINX@' . $this->_conf['table'] . '_struct', $this->_conf['fields'], 0, '');
        }
    }
    
    /**
     * 获取字段信息
     *
     * @return array
     */
    public function getfileds(){
        return $this->_conf['fields']['list'];   
    }

    /**
     * where
     *
     * @param unknown_type $where
     * @return unknown
     */
    public function where($str){
        $str = trim($str);
        if($str != ''){
            $instr = $in = $fun = $funstr = $blocks = array();
            // in , not in 
            preg_match_all('/([\w\.]+\s*(not\s*)?in\s*\(.+?\))/i', $str, $in);
            foreach($in[1] as $k => $v){
                $str = str_replace($v, '#####' . $k . '#####', $str);
                $tmp = preg_split('/\s*(not\s*)?in\s*/i', $v);
                $instr[$k] = str_replace(trim($tmp[0]), $this->escape($tmp[0]), $v);
            }
            // exists , not exists
            preg_match_all('/((?:not\s*)?exists\s*\(.+?\))/i', $str, $fun);
            foreach($fun[1] as $k => $v){
                $str = str_replace($v, '@@@@@' . $k . '@@@@@', $str);
                $funstr[$k] = preg_replace('/(\w+?)_tab/i', $this->_conf['pre'] . '\\1', $v);
            }
            
            $str = str_replace(')', ' ) ', str_replace('(', '( ', $str));
            preg_match_all('/([0-9a-zA-Z\.\_\#]+)\s*(\>\=|\<\=|\!\=|\=|\>|\<|like|or|and)\s*([^\s]+)/i', $str, $blocks);
            for($i = 0, $max = count($blocks[0]); $i < $max; $i++){
                $temp = $this->escape($blocks[1][$i]) . ' ' . $blocks[2][$i] . ' ';
                if(strpos($blocks[3][$i], '\'') === false && (strpos($blocks[3][$i], '"') !== false || strpos($blocks[3][$i], '.') !== false)){
                    $temp .= $this->escape($blocks[3][$i]);
                }else{
                    $temp .= $blocks[3][$i];
                }
                $str = preg_replace('/(\s|^)' . preg_quote($blocks[0][$i] , '/') . '(\s|$)/i', ' ' . $temp . ' ', $str);
            }
            if(!empty($instr)){
                foreach($instr as $k => $v){
                    $str = str_replace('#####' . $k . '#####', $v, $str);
                }
                $instr = null;
            }
            if(!empty($funstr)){
                foreach($funstr as $k => $v){
                    $str = str_replace('@@@@@' . $k . '@@@@@', $v, $str);
                }
                $funstr = null;
            }
            $this->_sql['where'][] = $str;
        }
        return $this;
    }

    /**
     * set 字段值
     *
     * @param unknown_type $k
     * @param unknown_type $v
     */
    public function set($k, $v){
        // 检测字段是否存在
        if(!isset($this->_conf['fields']['list'][$k])){
            core::error(core::L('db-field-not-exits', $k, $this->_conf['table_name']), 'Tab::set', 1, $k);
        }
        $this->data[$k] = $v;
        return $this;
    }

    /**
     * limit
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function limit($str){
        $str = trim($str);
        if($str != ''){
            $tmp = explode(',', $str);
            $this->_sql['limit'] = array_map('intval', $tmp);
        }
        return $this;
    }

    /**
     * union limit
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function ulimit($str){
        $str = trim($str);
        if($str != ''){
            $tmp = explode(',', $str);
            $this->_sql['ulimit'] = array_map('intval', $tmp);
        }
        return $this;
    }

    /**
     * 获取一条记录
     *
     * @return unknown
     */
    public function get(){
        $this->_sql['limit'] = array(
                1
        );
        return $this->_dbobj->get($this->parsesql('select'));
    }

    /**
     * 执行sql
     *
     * @return unknown
     */
    public function exec($sql, $param = array()){
        return $this->_dbobj->query($this->_format($sql, $param));
    }

    /**
     * 格式化sql
     *
     * @return unknown
     */
    private function _format($sql, $param = array()){
        $sql = preg_replace('/(\w+?)_tab/i', $this->_conf['pre'] . '\\1', $sql);
        if(!empty($param)){
            $m = array();
            preg_match_all('/\s*\%[a-zA-Z]\s*/i', $sql, $m);
            if(count($m[0]) > count($param)){
                core::error(core::L('wrong-param'), 'Tab::_format', 1, $sql);
            }
            $sql = vsprintf($sql, $param);
        }
        return $sql;
    }

    /**
     * union
     *
     * @param tab $obj
     * @param boolean $all
     * @return mixed
     */
    public function union(&$obj = null, $ctype = false){
        if(!empty($obj)){
            if(!is_array($obj)){
                $obj = array($obj);
            }
            $ctype = $ctype ? ($ctype == '1' ? 'all' : 'distinct') : '';
            $sql = '( ' . $this->parsesql('select') . ') ';
            foreach ($obj as $v){
                $sql .=  ' union ' . $ctype . '  ( ' . $v->parsesql('select') . ' ) ';
            }
            // order
            if(!empty($this->_sql['uorder'])){
                $sql .= ' order by ' . implode(' , ', $this->_sql['uorder']);
            }
            // limit
            if(!empty($this->_sql['ulimit'])){
                $sql .= ' limit  ' . implode(' , ', $this->_sql['ulimit']);
            }
            return $this->_dbobj->getall($sql);
        }
        return array();
    }

    /**
     * 输出sql
     *
     * @param unknown_type $sql
     */
    public function test($act = 'select'){
        if($this->_errmsg){
            return $this->_errmsg;
        }
        return $this->parsesql($act);
    }

    /**
     * 获取数据集合
     *
     * @return unknown
     */
    public function getall($sql = null, $param = array()){
        return $this->_dbobj->getall(empty($sql) ? $this->parsesql('select') : $this->_format($sql, $param), $this->_rkey);
    }

    /**
     * 设置返回数据数组的索引键
     *
     * @param unknown_type $k
     * @return unknown
     */
    public function rkey($k = null){
        $this->_rkey = empty($k) ? $this->_conf['fields']['pk'] : $k;
        return $this;
    }

    /**
     * union all
     *
     * @param tab $obj
     * @return mixed
     */
    public function unionall(&$obj){
        return $this->union($obj, 1);
    }

    /**
     * union distinct
     *
     * @param unknown_type $obj
     * @return unknown
     */
    public function uniondis(&$obj){
        return $this->union($obj, 2);
    }

    /**
     * 解析sql
     *
     * @return unknown
     */
    public function parsesql($act = false){
        $sep = IS_DEBUG ? " \n" : ' ';
        // action
        $this->_sql['act'] = $act ? $act : $this->_sql['act'];
        $sql = $this->_sql['act'] . ' ';

        // select
        if($this->_sql['act'] == 'select'){
            // fields
            if(isset($this->_sql['fields']) && !empty($this->_sql['fields'])){
                $sql .= implode(' , ', $this->_sql['fields']);
            }else{
                $sql .= ' * ';
            }
            $sql .= $sep;
            if(!$this->_keep){
                $this->_sql['fields'] = null;
            }

            $sql .= 'from ' . $this->_conf['table_name'] . $sep;

            // join
            if(!empty($this->_sql['join'])){
                $sql .= implode(" \n", $this->_sql['join']);
                if(!$this->_keep){
                    $this->_sql['join'] = null;
                }
            }
            $sql .= $sep;
            // where
            if(!empty($this->_sql['where'])){
                $sql .= 'where 1 = 1' . $sep;
                foreach($this->_sql['where'] as $v){
                    $sql .= 'and ( ' . $v . ' ) ' . $sep;
                }
                if(!$this->_keep){
                    $this->_sql['where'] = null;
                }
            }
            // group
            if(!empty($this->_sql['group'])){
                $sql .= 'group by ' . implode(' , ', $this->_sql['group']) . $sep;
                if(!$this->_keep){
                    $this->_sql['group'] = null;
                }
            }
            // order
            if(!empty($this->_sql['order'])){
                $sql .= 'order by ' . implode(' , ', $this->_sql['order']) . $sep;
                if($this->_keep){
                    $this->_sql['order'] = null;
                }
            }
            // limit
            if(!empty($this->_sql['limit'])){
                $sql .= 'limit  ' . implode(' , ', $this->_sql['limit']) . $sep;
                if($this->_keep){
                    $this->_sql['limit'] = null;
                }
            }
        }        // update
        else if($this->_sql['act'] == 'update'){
            $sql .= $this->_conf['table_name'] . ' set ';
            // set 数据
            if(!empty($this->data) && is_array($this->data)){
                foreach($this->data as $k => $v){
                    if($k != $this->_conf['fields']['pk']){
                        $this->data[$k] = $this->escape($k) . " = " . "'" . $v . "'" . $sep;
                    }else{
                        $this->where("{$k} = '{$v}'");
                        if($this->_initdata){
                            unset($this->data[$k]);
                        }
                    }
                }
                $sql .= implode(' , ', $this->data);
                if(!$this->_initdata){
                    $this->_initdata = true;
                }
            }            
            // 无数据 抛出异常信息
            else{
                core::error(core::L('no-data', $this->_conf['table']), 'tab::save', 1);
            }
            // where
            if(!empty($this->_sql['where'])){
                $sql .= 'where 1 = 1 ' . $sep;
                foreach($this->_sql['where'] as $v){
                    $sql .= 'and ( ' . $v . ' ) ' .  $sep;
                }
                $this->_sql['where'] = null;
                unset($this->_sql['where']);
            }
        }
        // delete
        else if($this->_sql['act'] == 'delete'){
            $sql .= ' from ' . $this->_conf['table_name'];
            // where
            if(!empty($this->_sql['where'])){
                $sql .= 'where 1 = 1 ' . $sep;
                foreach($this->_sql['where'] as $v){
                    $sql .= 'and ( ' . $v . ' ) ' . $sep;
                }
                $this->_sql['where'] = null;
                unset($this->_sql['where']);
            }
        }
        // insert
        else if($this->_sql['act'] == 'insert' || $this->_sql['act'] == 'replace'){
            $sql .= 'into ' . $this->_conf['table_name'] . '( ';
            $keys = $vals = array();
            // 数据
            if(!empty($this->data) && is_array($this->data)){
                foreach($this->data as $k => $v){
                    $keys[] = $this->escape($k);
                    $vals[] = "'" . $v . "'";
                }
                if($this->_initdata){
                    $this->data = array();
                }else{
                    $this->_initdata = true;
                }
            }
            // 无数据
            else{
                core::error(core::L('no-data', $this->_conf['table']), 'tab::save', 1);
            }
            $sql .= implode(' , ', $keys) . ' ) ' . $sep . ' values( ';
            $sql .= implode(' , ', $vals) . ' )';
        }
        
        // 最多只保留一次
        if($this->_initdata){
            $this->data = array();
        }else{
            $this->_initdata = true;
        }
        
        if(!$this->_keep){
            $this->_sql = array();
        }else{
            $this->_keep = FALSE;
        }

        return $sql;
    }

    /**
     * 更新
     */
    public function save(){
        $pkval = intval($this->data[$this->_conf['fields']['pk']] | $this->_sql['set'][$this->_conf['fields']['pk']][1]);
        if($pkval != '0' || !empty($this->_sql['where'])){
            // 若表主键值大于0 则执行update操作
            return $this->_validate(true) ? $this->_dbobj->update($this->parsesql('update')) : false;
        }else{
            // 执行 insert 操作
            return $this->_validate() ? $this->_dbobj->add($this->parsesql('insert')) : false;
        }
    }

    /**
     * 删除操作
     *
     * @return unknown
     */
    public function delete(){
        return $this->_dbobj->update($this->parsesql('delete'));
    }

    /**
     * 删除操作 别名
     *
     * @return unknown
     */
    public function del(){
        return $this->_dbobj->update($this->parsesql('delete'));
    }

    /**
     * 统计
     *
     * @return unknown
     */
    public function count($fields = null){
        if(!empty($fields)){
            $this->fields('count( ' . $fields . ' ) as nums');
        }else if(!empty($this->_sql['fields'])){
            $this->fields('count( ' . $this->_conf['fields']['pk'] . ' ) as nums');
        }else{
            $this->fields('count( * ) as nums');
        }
        return $this->_dbobj->count($this->parsesql('select'));
    }

    /**
     * 保存本次sql值
     */
    public function keep(){
        $this->_keep = TRUE;
        return $this;
    }

    /**
     * replace 操作
     *
     * @return unknown
     */
    public function replace($isset = false){
        if(!$this->_validate()){
            return false;
        }
        return $this->_dbobj->update($this->parsesql($isset ? 'replace_set' : 'replace'));
    }

    /**
     *  Join
     *
     * @example join('left' , 'user_tab' , 'id' , 'tab.uid');
     * @param unknown_type $tab
     *            表模型类名
     * @param unknown_type $key
     *            当前表字段 对应 tab
     * @param unknown_type $fkey 
     *            左表字段 默认对应当前tab
     * @return unknown
     */
    private function join($ctype = 'left' , $tab, $key, $fkey){
        if(!empty($tab) && !empty($key) && !empty($fkey)){
            if(strpos($tab, ' as ') !== false){
                $tmp = explode(' as ', $tab);
                $tab = trim($tmp[0]);
                $alias = trim($tmp[1]);
            }else{
                $alias = null;
            }
            $fkey = str_replace($tab . '.', '', trim($fkey));
            if(strpos($fkey , '.') !== false){
            	$fkey = $this->escape($fkey);
            }else{
            	$fkey = $this->escape((empty($alias) ? $tab : $alias) . '.' . $fkey);
            }
            $str = $ctype . " join " . $this->_gettabname($tab) . " ";
            $str .= (empty($alias) ? '' : "as $alias ") . ' on ' . $this->escape($key) . ' = ';
            $str .= $fkey;
            $this->_sql['join'][] = $str;
        }
        return $this;
    }
    
    /**
     * left join
     *
     * @param unknown_type $tab
     * @param unknown_type $key
     * @param unknown_type $fkey
     */
    public function leftjoin($tab , $key , $fkey){
        return $this->join('left' , $tab , $key , $fkey);
    }
    
    /**
     * right join
     *
     * @param unknown_type $tab
     * @param unknown_type $key
     * @param unknown_type $fkey
     */
    public function rightjoin($tab , $key , $fkey){
        return $this->join('right' , $tab , $key , $fkey);
    }
    
    /**
     * inner join 
     *
     * @param unknown_type $tab
     * @param unknown_type $key
     * @param unknown_type $fkey
     */
    public function innerjoin($tab , $key , $fkey){
        return $this->join('inner' , $tab , $key , $fkey);
    }
    

    /**
     * Order By
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function order($str){
        $str = trim($str);
        if($str != ''){
            $match = array();
            preg_match_all('/(.+?)(desc|asc)\s*?\,?/si', $str, $match);
            if(!empty($match[1])){
                for($i = 0, $max = count($match[1]); $i < $max; $i++){
                    $field = array();
                    $tmp = explode(',', $match[1][$i]);
                    foreach($tmp as $v){
                        if(trim($v) != ''){
                            $field[] = $this->escape($v);
                        }
                    }
                    $this->_sql['order'][] = implode(' , ', $field) . ' ' . $match[2][$i];
                }
                $match = null;
                unset($match);
            }else{
                // field(name , '1','2','3','4')
                $this->_sql['order'][] = preg_replace('/(\w+?)_tab/i', '`' . $this->_conf['pre'] . '\\1' . '`', strtolower(trim($str)));
            }
        }
        return $this;
    }

    /**
     * union order
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function uorder($str){
        $str = trim($str);
        if($str != ''){
            $match = array();
            preg_match_all('/(.+?)(desc|asc)\,?/si', $str, $match);
            for($i = 0, $max = count($match[1]); $i < $max; $i++){
                $field = array();
                $tmp = explode(',', $match[1][$i]);
                foreach($tmp as $v){
                    $field[] = $v;
                }
                $this->_sql['uorder'][] = implode(' , ', $field) . ' ' . $match[2][$i];
            }
            $match = null;
            unset($match);
        }
        return $this;
    }

    /**
     * Group By
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function group($str){
        $str = trim($str);
        if($str != ''){
            $tmp = explode(',', $str);
            foreach($tmp as $v){
                $this->_sql['group'][] = $this->escape($v);
            }
        }
        return $this;
    }

    /**
     * 设置查询字段
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function fields($str){
        $tmp = explode(',', trim(strtolower($str)));
        foreach($tmp as $v){
            if(strpos($v, ' as ') !== false){
                $temp = explode(' as ', $v);
                $matchs = array();
                // count() , sum() , max() , min() ...
                preg_match('/(\w+)\(\s*?([^\)]+?)\s*?\)/i', trim($temp[0]), $matchs);
                if($matchs[1] && $matchs[2]){
                    $matchs = array_map('trim', $matchs);
                    // distinct
                    if(($pos = strpos($matchs[2], 'distinct')) === false){
                        $this->_sql['fields'][] = $matchs[1] . '( ' . $this->escape($matchs[2]) . ' ) as ' . trim(($temp[1]));
                    }else{
                        $keyword = substr($matchs[2], 0, $pos + 8);
                        $field = substr($matchs[2], $pos + 8 - strlen($matchs[2]));
                        $this->_sql['fields'][] = $matchs[1] . '( ' . $keyword . ' ' . $this->escape($field) . ' ) as ' . trim(($temp[1]));
                    }
                }else{
                    $this->_sql['fields'][] = $this->escape($temp[0]) . ' as ' . trim(($temp[1]));
                }
            }else{
                $this->_sql['fields'][] = $this->escape($v);
            }
        }
        return $this;
    }

    /**
     * 字段转义
     *
     * @param unknown_type $str
     * @return unknown
     */
    public function escape($str){
        $ret = $str = strtolower(trim($str));
        if(is_numeric($str)){
        	$ret = intval($str);
        }else if(isset($this->_conf['fields']['list'][$str])){
            $ret = $this->_conf['table_name'] . '.`' . $str . '`';
        }else{
            if(strpos($str, '.') !== false){
                $tmp = explode('.', $str);
                // info_tab.id as iid
                if(strpos($str, ' as ') !== false){
                    $temp = explode(' as ', str_replace($tmp[0] . '.', '', $str));
                    $ret = $this->_gettabname($tmp[0]) . '.`' . trim($temp[0]) . '` as `' . trim($temp[1]) . '`';
                }else{
                    if(trim($tmp[1]) == '*'){
                        $ret = $this->_gettabname($tmp[0]) . '.*';
                    }else{
                        $ret = $this->_gettabname($tmp[0]) . '.`' . trim($tmp[1]) . '`';
                    }
                }
            }else{
                $ret = ($str == '*' || substr($str, 0, 5) == '#####') ? $str : ('`' . $str . '`');
            }
        }
        return $ret;
    }

    /**
     *
     *
     * 加载表单数据至当前对象data属性
     *
     * @param unknown_type $var
     * @return unknown
     */
    public function load($var = null){
        $this->_errmsg = array();
        if(!empty($var) && is_array($var)){
            $data = $var;
        }else{
            $data = core::getgpc(empty($var) ? $this->_conf['table'] : $var);
        }
        foreach($data as $k => $v){
            // 过滤非当前表字段的内容
            if(isset($this->_conf['fields']['list'][$k])){
                $this->data[$k] = $v;
            }
        }
        $data = null;
        return $this->_validate(isset($this->data[$this->_conf['fields']['pk']]) ? $this->data[$this->_conf['fields']['pk']] : true);
    }

    /**
     * 数据验证
     *
     * @return unknown
     */
    private function _validate($isupdate = false){
        // 默认返回
        $ret = true;

        // 当操作为插入的时候 , 合并默认数据
        if(!empty($this->default) && !$isupdate){
            $this->data = array_merge($this->default, $this->data);
        }

        // 执行过滤
        foreach($this->data as $k => $v){
            if(isset($this->filter[$k])){
                $this->data[$k] = call_user_func_array($this->filter[$k], array(
                        $this->data[$k]
                ));
            }else{
                $this->data[$k] = filter::normal($v);
            }
        }
        unset($v);
        
        // 数据验证
        if(!empty($this->validate)){
            foreach($this->validate as $k => $v){
                // 执行更新时候,若数据不存在,跳过; 只验证存在的数据
                if(!isset($this->data[$v['key']]) && $isupdate){
                    continue;
                }
                // 数据验证
                switch (intval($v['type'])){
                    case 0:
                        // 使用验证类提供的规则验证
                        if(!(bool)preg_match(filter::$rules[$v['rule']], $this->data[$v['key']])){
                            $ret = false;
                            $this->_errmsg[$v['key']] = $v['msg'];
                        }
                        break;
                    case 1:
                        // 使用自定义的正则表达式验证
                        try{
                            $result = preg_match($v['rule'], $this->data[$v['key']]);
                        }catch(Exception $e){
                            core::error(core::L('regex-error', $v['rule']));
                        }
                        if(!$result){
                            $ret = false;
                            $this->_errmsg[$v['key']] = $v['msg'];
                        }
                        break;
                    case 2:
                        // 使用自定义方法验证
                        if($v['rule'][0] == get_class($this)){
                            if(!(bool)call_user_func_array(array(
                                    $this,
                                    $v['rule'][1]
                            ), array(
                                    $this->data[$v['key']],
                                    $this->data[$this->_conf['fields']['pk']]
                            ))){
                                $ret = false;
                                $this->_errmsg[$v['key']] = $v['msg'];
                            }
                        }else if(!(bool)call_user_func_array($v['rule'], array(
                                $this->data[$v['key']],
                                $this->data[$this->_conf['fields']['pk']]
                        ))){
                            $ret = false;
                            $this->_errmsg[$v['key']] = $v['msg'];
                        }
                        break;
                }
            }
        }
        return $ret;
    }

    /**
     * 根据类名获取表名
     *
     * @param unknown_type $class
     * @return unknown
     */
    private function _gettabname($class){
        return preg_replace('/(\w+?)_tab/i', '`' . $this->_conf['pre'] . '\\1' . '`', strtolower(trim($class)));
    }

    /**
     * 清除sql条件
     *
     * @param unknown_type $key
     * @return unknown
     */
    public function clear($key){
        if(isset($this->_sql[$key])){
            $this->_sql[$key] = null;
            unset($this->_sql[$key]);
        }
        return $this;
    }

    /**
     * 获取错误消息
     *
     * @return unknown
     */
    public function geterr(){
        $errmsg = $this->_errmsg;
        $this->_errmsg = null;
        return $errmsg;
    }
}
?>