1 Star 0 Fork 0

2you / gsql

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
gsql.go 11.49 KB
一键复制 编辑 原始数据 按行查看 历史
2you 提交于 2020-06-01 09:41 . update function Query.First
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
package gsql
import (
"bytes"
"database/sql"
"encoding/binary"
"fmt"
"log"
"os"
"reflect"
"strconv"
"time"
)
type FieldType int
const (
ftUnknown FieldType = iota
ftInt
ftUint
ftString
ftFloat
ftBool
ftTime
ftBytes
)
type dbConn interface {
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
Exec(query string, args ...interface{}) (sql.Result, error)
Prepare(query string) (*sql.Stmt, error)
}
type DBx struct {
db *sql.DB
}
var glog *log.Logger
func init() {
glog = log.New(os.Stdout, `gsql>`, log.Lshortfile|log.Ldate|log.Ltime)
}
func New(driverName, dataSourceName string) (dbx *DBx, err error) {
dbx = new(DBx)
dbx.db, err = sql.Open(driverName, dataSourceName)
//glog.Println(err)
return dbx, err
}
func (this *DBx) Close() error {
return this.db.Close()
}
func (this *DBx) NewQuery(args ...interface{}) *Query {
query := new(Query)
query.conn = this.db
query.isPrepare = false
if len(args) > 0 {
if val, ok := args[0].(bool); ok {
query.isPrepare = val
}
}
return query
}
func (this *DBx) NewTrans() (t *Transaction, e error) {
t = new(Transaction)
t.tx, e = this.db.Begin()
return t, e
}
type Transaction struct {
tx *sql.Tx
}
func (this *Transaction) NewQuery(args ...interface{}) *Query {
query := new(Query)
query.conn = this.tx
if len(args) > 0 {
query.isPrepare = true
}
return query
}
func (this *Transaction) Commit() error {
return this.tx.Commit()
}
func (this *Transaction) Rollback() error {
return this.tx.Rollback()
}
type Query struct {
conn dbConn
rows *sql.Rows
fields *Fields
isPrepare bool
stmt *sql.Stmt
sqlStr string
sqlArgs []interface{}
sqlArgs_prepare []interface{}
}
func (this *Query) checkError() {
}
func (this *Query) SetSQL(query string, args ...interface{}) *Query {
this.Close()
this.sqlStr = query
this.sqlArgs = args
return this
}
func (this *Query) GetOne(args ...interface{}) (err error) {
if err = this.Open(args...); err != nil {
return err
}
if !this.Next() {
if err = this.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
return err
}
func (this *Query) Open(args ...interface{}) (err error) {
this.sqlArgs_prepare = args
return this.First()
}
func (this *Query) Exec(args ...interface{}) (ret sql.Result, err error) {
if this.isPrepare {
if this.stmt == nil {
if this.stmt, err = this.conn.Prepare(this.sqlStr); err != nil {
return nil, err
}
}
return this.stmt.Exec(args...)
}
return this.conn.Exec(this.sqlStr, this.sqlArgs...)
}
func (this *Query) Close() error {
if this.rows == nil {
return fmt.Errorf(`no connection`)
}
defer func() {
this.rows = nil
this.stmt = nil
this.fields = nil
}()
if this.stmt != nil {
this.stmt.Close()
}
return this.rows.Close()
}
func (this *Query) First() (err error) {
if this.rows != nil {
this.Close()
}
if this.isPrepare {
if this.stmt == nil {
if this.stmt, err = this.conn.Prepare(this.sqlStr); err != nil {
return err
}
}
this.rows, err = this.stmt.Query(this.sqlArgs_prepare...)
} else {
this.rows, err = this.conn.Query(this.sqlStr, this.sqlArgs...)
}
if err == nil {
this.fields = newFields(this.rows)
}
return err
}
func (this *Query) Next() bool {
this.checkError()
if !this.rows.Next() {
return false
}
this.rows.Scan(this.fields.vals...)
return true
}
func (this *Query) FieldCount() int {
this.checkError()
return this.fields.fieldCount
}
func (this *Query) FieldById(id int) *Field {
this.checkError()
return this.fields.fields[id]
}
func (this *Query) FieldByName(name string) *Field {
this.checkError()
if field, ok := this.fields.list[name]; ok {
return field
}
return nil
}
type Field struct {
fieldName string
fieldValue interface{}
dataType FieldType
refValue reflect.Value
//asInt *int64
//asUint *uint64
//asFloat *float64
//asBool *bool
//asString *string
//asBytes *[]byte
//asTime *time.Time
//
//toInt *int64
//toUint *uint64
//toFloat *float64
//toBool *bool
//toString *string
//toBytes *[]byte
//toTime *time.Time
//asErr error
//toErr error
}
func newField(name string) *Field {
p := new(Field)
p.fieldName = name
return p
}
func (this *Field) getDataType() FieldType {
this.refValue = reflect.ValueOf(this.fieldValue)
if !this.refValue.IsValid() {
return ftUnknown
}
switch this.refValue.Kind() {
case reflect.Int:
fallthrough
case reflect.Int8:
fallthrough
case reflect.Int16:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
return ftInt
case reflect.Uint:
fallthrough
case reflect.Uint8:
fallthrough
case reflect.Uint16:
fallthrough
case reflect.Uint32:
fallthrough
case reflect.Uint64:
return ftUint
case reflect.Float32:
fallthrough
case reflect.Float64:
return ftFloat
case reflect.String:
return ftString
case reflect.Bool:
return ftBool
case reflect.Slice:
return ftBytes
case reflect.Struct:
switch this.fieldValue.(type) {
case time.Time:
return ftTime
}
}
glog.Println(this.refValue.Kind())
return ftUnknown
}
func (this *Field) IsNull() bool {
return this.getDataType() == ftUnknown
}
func (this *Field) AsInt64() (n int64, e error) {
//if this.asInt != nil {
// return *this.asInt, this.asErr
//}
n = 0
switch this.getDataType() {
case ftInt:
n = this.refValue.Int()
case ftUint:
n = int64(this.ToUint64())
case ftFloat:
n = int64(this.ToFloat64())
case ftBool:
if this.ToBool() {
n = 1
}
case ftString:
n, e = strconv.ParseInt(this.ToString(), 10, 64)
case ftBytes:
e = binary.Read(bytes.NewBuffer(this.ToBytes()), binary.BigEndian, &n)
case ftTime:
n = this.ToTime().UnixNano()
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as int`, this.refValue.Type())
}
//this.asInt = &n
//this.asErr = e
return n, e
}
func (this *Field) ToInt64() (n int64) {
n, _ = this.AsInt64()
return n
}
func (this *Field) AsUint64() (n uint64, e error) {
//if this.asUint != nil {
// return *this.asUint, this.asErr
//}
n = 0
switch this.getDataType() {
case ftUint:
n = this.refValue.Uint()
case ftInt:
n = uint64(this.ToInt64())
case ftFloat:
n = uint64(this.ToFloat64())
case ftBool:
if this.ToBool() {
n = 1
}
case ftString:
n, e = strconv.ParseUint(this.ToString(), 10, 64)
case ftBytes:
e = binary.Read(bytes.NewBuffer(this.ToBytes()), binary.BigEndian, &n)
case ftTime:
n = uint64(this.ToTime().UnixNano())
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as uint`, this.refValue.Type())
}
//this.asUint = &n
//this.asErr = e
return n, e
}
func (this *Field) ToUint64() uint64 {
n, _ := this.AsUint64()
return n
}
func (this *Field) AsFloat32() (f float32, e error) {
f64, e := this.AsFloat64()
return float32(f64), e
}
func (this *Field) ToFloat32() float32 {
f, _ := this.AsFloat32()
return f
}
func (this *Field) AsFloat64() (f float64, e error) {
//if this.asFloat != nil {
// return *this.asFloat, nil
//}
f = 0
switch this.getDataType() {
case ftFloat:
f = this.refValue.Float()
case ftInt:
f = float64(this.ToInt64())
case ftUint:
f = float64(this.ToUint64())
case ftBool:
if this.ToBool() {
f = 1
}
case ftString:
f, e = strconv.ParseFloat(this.ToString(), 64)
case ftBytes:
e = binary.Read(bytes.NewBuffer(this.ToBytes()), binary.BigEndian, &f)
case ftTime:
f = float64(this.ToTime().UnixNano())
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as float`, this.refValue.Type())
}
//this.asFloat = &f
//this.asErr = e
return f, e
}
func (this *Field) ToFloat64() float64 {
f, _ := this.AsFloat64()
return f
}
func (this *Field) AsBytes() (b []byte, e error) {
//if this.asBytes != nil {
// return *this.asBytes, this.asErr
//}
buf := bytes.NewBuffer([]byte{})
switch this.getDataType() {
case ftBytes:
b = this.refValue.Bytes()
buf.Write(b)
case ftInt:
e = binary.Write(buf, binary.BigEndian, this.ToInt64())
case ftUint:
e = binary.Write(buf, binary.BigEndian, this.ToUint64())
case ftFloat:
e = binary.Write(buf, binary.BigEndian, this.ToFloat64())
case ftBool:
e = binary.Write(buf, binary.BigEndian, this.ToBool())
case ftString:
buf.WriteString(this.ToString())
case ftTime:
e = binary.Write(buf, binary.BigEndian, this.ToTime().UnixNano())
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as bytes`, this.refValue.Type())
}
//this.asBytes = &b
//this.asErr = e
return b, e
}
func (this *Field) ToBytes() []byte {
b, _ := this.AsBytes()
return b
}
func (this *Field) AsBool() (b bool, e error) {
//if this.asBool != nil {
// return *this.asBool, this.asErr
//}
b = false
switch this.getDataType() {
case ftBool:
b = this.refValue.Bool()
case ftInt:
b = this.ToInt64() != 0
case ftUint:
b = this.ToUint64() != 0
case ftFloat:
b = this.ToFloat64() != 0
case ftString:
b, e = strconv.ParseBool(this.ToString())
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as bool`, this.refValue.Type())
}
//this.asBool = &b
//this.asErr = e
return b, e
}
func (this *Field) ToBool() bool {
b, _ := this.AsBool()
return b
}
func (this *Field) AsString() (s string, e error) {
//if this.asString != nil {
// return *this.asString, this.asErr
//}
s = ``
switch this.getDataType() {
case ftString:
s = this.refValue.String()
case ftInt:
s = strconv.FormatInt(this.refValue.Int(), 10)
case ftUint:
s = strconv.FormatUint(this.refValue.Uint(), 10)
case ftFloat:
s = strconv.FormatFloat(this.refValue.Float(), 'f', -1, 64)
case ftBool:
s = strconv.FormatBool(this.refValue.Bool())
case ftBytes:
s = string(this.refValue.Bytes())
case ftTime:
s = this.ToTime().String()
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as string`, this.refValue.Type())
}
//this.asString = &s
//this.asErr = e
return s, e
}
func (this *Field) ToString() (s string) {
s, _ = this.AsString()
return s
}
func (this *Field) AsTime() (t time.Time, e error) {
//if this.asTime != nil {
// return *this.asTime, this.asErr
//}
t = time.Unix(0, 0)
switch this.getDataType() {
case ftTime:
t = this.fieldValue.(time.Time)
case ftUnknown:
e = fmt.Errorf(`field is null`)
default:
e = fmt.Errorf(`type [%s] can't as time`, this.refValue.Type())
}
//this.asTime = &t
//this.asErr = e
return t, e
}
func (this *Field) ToTime() (t time.Time) {
//if this.toTime != nil {
// return *this.toTime
//}
t = time.Unix(0, 0)
switch this.getDataType() {
case ftTime:
t = this.fieldValue.(time.Time)
case ftInt:
n := this.ToInt64()
t = time.Unix(n/int64(time.Second), n%int64(time.Second))
case ftUint:
n := int64(this.ToUint64())
t = time.Unix(n/int64(time.Second), n%int64(time.Second))
case ftFloat:
n := int64(this.ToFloat64())
t = time.Unix(n/int64(time.Second), n%int64(time.Second))
}
//this.toTime = &t
return t
}
type Fields struct {
//rows *sql.Rows
fieldCount int
list map[string]*Field
fields []*Field
vals []interface{}
}
func newFields(rows *sql.Rows) *Fields {
p := new(Fields)
p.list = make(map[string]*Field)
//p.rows = rows
names, _ := rows.Columns()
p.fieldCount = len(names)
p.fields = make([]*Field, p.fieldCount)
p.vals = make([]interface{}, p.fieldCount)
for id, name := range names {
field := newField(name)
field.dataType = ftUnknown
p.list[name] = field
p.fields[id] = field
p.vals[id] = &field.fieldValue
}
return p
}
Go
1
https://gitee.com/2you/gsql.git
git@gitee.com:2you/gsql.git
2you
gsql
gsql
07b96448148c

搜索帮助