func (this *DAOProxy) DelRecords(where string, params ...interface{}) int {
	return this.DBWriter.Execute("delete from "+this.table+" where "+where, params...)
}
DelRecords {{{ Is Dangerous!
package dao
import (
	"bytes"
	"fmt"
	"github.com/mlaoji/ygo/lib"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"time"
)
type DAOProxy struct {
	DBWriter, DBReader *lib.MysqlClient
	table              string
	primary            string
	defaultFields      string  
	fields             string  
	countField         string  
	index              string  
	forceMaster        bool    
	bind               interface{}
}
func (this *DAOProxy) Init(conf ...string) {  
	master_conf := "mysql_master"
	slave_conf := "mysql_slave"
	if len(conf) > 0 {
		master_conf = conf[0]
		slave_conf = conf[0]
	}
	if len(conf) > 1 {
		slave_conf = conf[1]
	}
	slave_confs := lib.Conf.GetSlice(slave_conf, "slaves")
	if len(slave_confs) > 0 {
		rand.Seed(int64(time.Now().Nanosecond()))
		idx := rand.Intn(len(slave_confs))
		slave_conf = slave_confs[idx]
	}
	this.defaultFields = "*"
	this.DBWriter = lib.Mysql.Get(master_conf)
	this.DBReader = lib.Mysql.Get(slave_conf)
}  
func (this *DAOProxy) InitTx(tx *lib.MysqlClient) {  
	this.defaultFields = "*"
	this.DBWriter = tx
	this.DBReader = tx
}  
func (this *DAOProxy) SetTable(table string) {
	this.table = table
}
func (this *DAOProxy) GetTable() string {
	return this.table
}
func (this *DAOProxy) SetPrimary(field string) {
	this.primary = field
}
func (this *DAOProxy) GetPrimary() string {
	return this.primary
}
func (this *DAOProxy) SetCountField(field string) *DAOProxy {
	this.countField = field
	return this
}
func (this *DAOProxy) GetCountField() string {
	field := "1"
	if "" != this.countField {
		field = this.countField
		this.countField = ""
	}
	return field
}
func (this *DAOProxy) SetDefaultFields(fields string) *DAOProxy {
	this.defaultFields = fields
	return this
}
func (this *DAOProxy) SetFields(fields string) *DAOProxy {
	this.fields = fields
	return this
}
func (this *DAOProxy) GetFields() string {
	fields := this.defaultFields
	if "" != this.fields {
		fields = this.fields
		this.fields = ""
	}
	return fields
}
func (this *DAOProxy) UseIndex(idx string) *DAOProxy {
	this.index = idx
	return this
}
func (this *DAOProxy) UseMaster(flag ...bool) *DAOProxy {
	use := true
	if len(flag) > 0 {
		use = flag[0]
	}
	this.forceMaster = use
	return this
}
func (this *DAOProxy) GetDBReader() *lib.MysqlClient {
	if this.forceMaster {
		this.forceMaster = false
		return this.DBWriter
	}
	return this.DBReader
}
func (this *DAOProxy) Bind(objPtr interface{}) *DAOProxy {  
	if reflect.ValueOf(objPtr).Kind() != reflect.Ptr {
		panic("needs a pointer to a slice or a struct")
	}
	this.bind = objPtr
	this.parseFields(objPtr)
	return this
}  
func (this *DAOProxy) parseFields(objPtr interface{}) {
	objVal := reflect.Indirect(reflect.ValueOf(objPtr))
	data := map[string]interface{}{}
	var valPtr interface{}
	if objVal.Kind() == reflect.Slice {
		sliceElementType := objVal.Type().Elem()
		if sliceElementType.Kind() == reflect.Ptr {
			if sliceElementType.Elem().Kind() == reflect.Struct {
				valPtr = reflect.New(sliceElementType.Elem()).Interface()
			} else {
				panic("need type []*Struct")
			}
		} else if sliceElementType.Kind() == reflect.Struct {
			valPtr = reflect.New(sliceElementType).Interface()
		} else {
			panic("need type []Struct or []*Struct")
		}
	} else if objVal.Kind() == reflect.Struct {
		valPtr = objVal.Interface()
	} else {
		panic("needs a pointer to a slice or a struct")
	}
	data = this.preParams(valPtr)
	buf := bytes.NewBufferString("")
	i := 0
	for k, _ := range data {
		if i > 0 {
			buf.WriteString(",")
		}
		buf.WriteString(k)
		i++
	}
	this.fields = buf.String()
}  
func (this *DAOProxy) parseRecord(data map[string]interface{}) {
	this.Fillin(this.bind, data)
}  
func (this *DAOProxy) parseRecords(data []map[string]interface{}) {
	rowsSlicePtr := this.bind
	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
	if sliceValue.Kind() != reflect.Slice {
		panic("needs a pointer to a slice")
	}
	sliceElementType := sliceValue.Type().Elem()
	isptr := false
	if sliceElementType.Kind() == reflect.Ptr {
		isptr = true
	}
	for _, v := range data {
		if isptr {
			newValue := reflect.New(sliceElementType.Elem())
			this.Fillin(newValue.Interface(), v)
			sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(newValue.Interface())))
		} else {
			newValue := reflect.New(sliceElementType)
			this.Fillin(newValue.Interface(), v)
			sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
		}
	}
}  
func (this *DAOProxy) Fillin(obj interface{}, data map[string]interface{}) {  
	dataStruct := reflect.Indirect(reflect.ValueOf(obj))
	typ := dataStruct.Type()
	numField := typ.NumField()
	for i := 0; i < numField; i++ {
		typField := typ.Field(i)
		valField := dataStruct.Field(i)
		if !valField.CanSet() {
			continue
		}
		tag := typField.Tag.Get("db")
		if tag == "-" || tag == "nil" {
			continue
		}
		if tag == "" {
			tag = strings.ToLower(typField.Name)
		}
		value, ok := data[tag]
		if !ok {
			continue
		}
		kind := typField.Type.Kind()
		switch kind {
		case reflect.Bool:
			b, err := strconv.ParseBool(value.(string))
			if err != nil {
				panic(err)
			}
			valField.SetBool(b)
		case reflect.String:
			valField.SetString(value.(string))
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			i, err := strconv.ParseInt(value.(string), 0, 64)
			if err != nil {
				panic(err)
			}
			valField.SetInt(i)
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			u, err := strconv.ParseUint(value.(string), 0, 64)
			if err != nil {
				panic(err)
			}
			valField.SetUint(u)
		case reflect.Float32, reflect.Float64:
			f, err := strconv.ParseFloat(value.(string), 64)
			if err != nil {
				panic(err)
			}
			valField.SetFloat(f)
		default:
			panic(fmt.Sprintf("unsupported type: %s", kind.String()))
		}
	}
}  
func (this *DAOProxy) preParams(obj interface{}) map[string]interface{} {
	objVal := reflect.ValueOf(obj)
	if objVal.Kind() == reflect.Ptr {
		objVal = objVal.Elem()
	}
	t := objVal.Type()
	if objVal.Kind() == reflect.Map {  
		return objVal.Interface().(map[string]interface{})
	}
	if objVal.Kind() != reflect.Struct {
		panic("need a [map or Struct ] or a pointer to [map or Struct ]")
	}
	var data = make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		tag := t.Field(i).Tag.Get("db")
		if tag == "-" || tag == "nil" {
			continue
		}
		if tag == "" {
			tag = strings.ToLower(t.Field(i).Name)
		}
		data[tag] = objVal.Field(i).Interface()
	}
	return data
}  
func (this *DAOProxy) FuncParam(param interface{}) string {  
	return this.DBReader.FuncParam(param)
}  
func (this *DAOProxy) Execute(sql string, params ...interface{}) int {  
	return this.DBWriter.Execute(sql, params...)
}  
func (this *DAOProxy) Query(sql string, params ...interface{}) []map[string]interface{} {  
	list := this.GetDBReader().GetAll(sql, params...)
	if len(list) > 0 && nil != this.bind {
		this.parseRecords(list)
	}
	return list
}  
func (this *DAOProxy) AddRecord(vals interface{}) int {
	return this.DBWriter.Insert(this.table, this.preParams(vals))
}  
func (this *DAOProxy) SetRecord(vals interface{}, id int) int {
	return this.DBWriter.Update(this.table, this.preParams(vals), this.primary+"=?", id)
}  
func (this *DAOProxy) SetRecordBy(vals interface{}, where string, params ...interface{}) int {
	return this.DBWriter.Update(this.table, this.preParams(vals), where, params...)
}  
func (this *DAOProxy) ResetRecord(vals interface{}) int {
	return this.DBWriter.Replace(this.table, this.preParams(vals))
}  
func (this *DAOProxy) GetRecord(id int) map[string]interface{} {
	row := this.GetDBReader().GetRow("select "+this.GetFields()+" from "+this.table+" where "+this.primary+"=?", id)
	if len(row) > 0 && nil != this.bind {
		this.parseRecord(row)
	}
	return row
}  
func (this *DAOProxy) DelRecord(id int) int {
	return this.DBWriter.Execute("delete from "+this.table+" where "+this.primary+"=? limit 1", id)
}  
func (this *DAOProxy) DelRecordBy(where string, params ...interface{}) int {
	return this.DBWriter.Execute("delete from "+this.table+" where "+where+" limit 1", params...)
}  