aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/go-xorm/core/rows.go
diff options
context:
space:
mode:
authorUnknwon <u@gogs.io>2017-02-09 19:48:13 -0500
committerUnknwon <u@gogs.io>2017-02-09 19:48:13 -0500
commit2fd69f13d9599a6c58b47225565163fd7d87889f (patch)
treefd19e868e1c2e95a5fb83a268f6e393669d6ee79 /vendor/github.com/go-xorm/core/rows.go
parenteb66060cd7b9bce996b1d75ae80ce1ef31d5ce62 (diff)
vendor: check in vendors
Bye bye glide...
Diffstat (limited to 'vendor/github.com/go-xorm/core/rows.go')
-rw-r--r--vendor/github.com/go-xorm/core/rows.go380
1 files changed, 380 insertions, 0 deletions
diff --git a/vendor/github.com/go-xorm/core/rows.go b/vendor/github.com/go-xorm/core/rows.go
new file mode 100644
index 00000000..c4dec23e
--- /dev/null
+++ b/vendor/github.com/go-xorm/core/rows.go
@@ -0,0 +1,380 @@
+package core
+
+import (
+ "database/sql"
+ "errors"
+ "reflect"
+ "sync"
+)
+
+type Rows struct {
+ *sql.Rows
+ Mapper IMapper
+}
+
+func (rs *Rows) ToMapString() ([]map[string]string, error) {
+ cols, err := rs.Columns()
+ if err != nil {
+ return nil, err
+ }
+
+ var results = make([]map[string]string, 0, 10)
+ for rs.Next() {
+ var record = make(map[string]string, len(cols))
+ err = rs.ScanMap(&record)
+ if err != nil {
+ return nil, err
+ }
+ results = append(results, record)
+ }
+ return results, nil
+}
+
+// scan data to a struct's pointer according field index
+func (rs *Rows) ScanStructByIndex(dest ...interface{}) error {
+ if len(dest) == 0 {
+ return errors.New("at least one struct")
+ }
+
+ vvvs := make([]reflect.Value, len(dest))
+ for i, s := range dest {
+ vv := reflect.ValueOf(s)
+ if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
+ return errors.New("dest should be a struct's pointer")
+ }
+
+ vvvs[i] = vv.Elem()
+ }
+
+ cols, err := rs.Columns()
+ if err != nil {
+ return err
+ }
+ newDest := make([]interface{}, len(cols))
+
+ var i = 0
+ for _, vvv := range vvvs {
+ for j := 0; j < vvv.NumField(); j++ {
+ newDest[i] = vvv.Field(j).Addr().Interface()
+ i = i + 1
+ }
+ }
+
+ return rs.Rows.Scan(newDest...)
+}
+
+var (
+ fieldCache = make(map[reflect.Type]map[string]int)
+ fieldCacheMutex sync.RWMutex
+)
+
+func fieldByName(v reflect.Value, name string) reflect.Value {
+ t := v.Type()
+ fieldCacheMutex.RLock()
+ cache, ok := fieldCache[t]
+ fieldCacheMutex.RUnlock()
+ if !ok {
+ cache = make(map[string]int)
+ for i := 0; i < v.NumField(); i++ {
+ cache[t.Field(i).Name] = i
+ }
+ fieldCacheMutex.Lock()
+ fieldCache[t] = cache
+ fieldCacheMutex.Unlock()
+ }
+
+ if i, ok := cache[name]; ok {
+ return v.Field(i)
+ }
+
+ return reflect.Zero(t)
+}
+
+// scan data to a struct's pointer according field name
+func (rs *Rows) ScanStructByName(dest interface{}) error {
+ vv := reflect.ValueOf(dest)
+ if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
+ return errors.New("dest should be a struct's pointer")
+ }
+
+ cols, err := rs.Columns()
+ if err != nil {
+ return err
+ }
+
+ newDest := make([]interface{}, len(cols))
+ var v EmptyScanner
+ for j, name := range cols {
+ f := fieldByName(vv.Elem(), rs.Mapper.Table2Obj(name))
+ if f.IsValid() {
+ newDest[j] = f.Addr().Interface()
+ } else {
+ newDest[j] = &v
+ }
+ }
+
+ return rs.Rows.Scan(newDest...)
+}
+
+type cacheStruct struct {
+ value reflect.Value
+ idx int
+}
+
+var (
+ reflectCache = make(map[reflect.Type]*cacheStruct)
+ reflectCacheMutex sync.RWMutex
+)
+
+func ReflectNew(typ reflect.Type) reflect.Value {
+ reflectCacheMutex.RLock()
+ cs, ok := reflectCache[typ]
+ reflectCacheMutex.RUnlock()
+
+ const newSize = 200
+
+ if !ok || cs.idx+1 > newSize-1 {
+ cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), newSize, newSize), 0}
+ reflectCacheMutex.Lock()
+ reflectCache[typ] = cs
+ reflectCacheMutex.Unlock()
+ } else {
+ reflectCacheMutex.Lock()
+ cs.idx = cs.idx + 1
+ reflectCacheMutex.Unlock()
+ }
+ return cs.value.Index(cs.idx).Addr()
+}
+
+// scan data to a slice's pointer, slice's length should equal to columns' number
+func (rs *Rows) ScanSlice(dest interface{}) error {
+ vv := reflect.ValueOf(dest)
+ if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice {
+ return errors.New("dest should be a slice's pointer")
+ }
+
+ vvv := vv.Elem()
+ cols, err := rs.Columns()
+ if err != nil {
+ return err
+ }
+
+ newDest := make([]interface{}, len(cols))
+
+ for j := 0; j < len(cols); j++ {
+ if j >= vvv.Len() {
+ newDest[j] = reflect.New(vvv.Type().Elem()).Interface()
+ } else {
+ newDest[j] = vvv.Index(j).Addr().Interface()
+ }
+ }
+
+ err = rs.Rows.Scan(newDest...)
+ if err != nil {
+ return err
+ }
+
+ srcLen := vvv.Len()
+ for i := srcLen; i < len(cols); i++ {
+ vvv = reflect.Append(vvv, reflect.ValueOf(newDest[i]).Elem())
+ }
+ return nil
+}
+
+// scan data to a map's pointer
+func (rs *Rows) ScanMap(dest interface{}) error {
+ vv := reflect.ValueOf(dest)
+ if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
+ return errors.New("dest should be a map's pointer")
+ }
+
+ cols, err := rs.Columns()
+ if err != nil {
+ return err
+ }
+
+ newDest := make([]interface{}, len(cols))
+ vvv := vv.Elem()
+
+ for i, _ := range cols {
+ newDest[i] = ReflectNew(vvv.Type().Elem()).Interface()
+ //v := reflect.New(vvv.Type().Elem())
+ //newDest[i] = v.Interface()
+ }
+
+ err = rs.Rows.Scan(newDest...)
+ if err != nil {
+ return err
+ }
+
+ for i, name := range cols {
+ vname := reflect.ValueOf(name)
+ vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
+ }
+
+ return nil
+}
+
+/*func (rs *Rows) ScanMap(dest interface{}) error {
+ vv := reflect.ValueOf(dest)
+ if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
+ return errors.New("dest should be a map's pointer")
+ }
+
+ cols, err := rs.Columns()
+ if err != nil {
+ return err
+ }
+
+ newDest := make([]interface{}, len(cols))
+ err = rs.ScanSlice(newDest)
+ if err != nil {
+ return err
+ }
+
+ vvv := vv.Elem()
+
+ for i, name := range cols {
+ vname := reflect.ValueOf(name)
+ vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
+ }
+
+ return nil
+}*/
+type Row struct {
+ rows *Rows
+ // One of these two will be non-nil:
+ err error // deferred error for easy chaining
+}
+
+func (row *Row) Columns() ([]string, error) {
+ if row.err != nil {
+ return nil, row.err
+ }
+ return row.rows.Columns()
+}
+
+func (row *Row) Scan(dest ...interface{}) error {
+ if row.err != nil {
+ return row.err
+ }
+ defer row.rows.Close()
+
+ for _, dp := range dest {
+ if _, ok := dp.(*sql.RawBytes); ok {
+ return errors.New("sql: RawBytes isn't allowed on Row.Scan")
+ }
+ }
+
+ if !row.rows.Next() {
+ if err := row.rows.Err(); err != nil {
+ return err
+ }
+ return sql.ErrNoRows
+ }
+ err := row.rows.Scan(dest...)
+ if err != nil {
+ return err
+ }
+ // Make sure the query can be processed to completion with no errors.
+ return row.rows.Close()
+}
+
+func (row *Row) ScanStructByName(dest interface{}) error {
+ if row.err != nil {
+ return row.err
+ }
+ defer row.rows.Close()
+
+ if !row.rows.Next() {
+ if err := row.rows.Err(); err != nil {
+ return err
+ }
+ return sql.ErrNoRows
+ }
+ err := row.rows.ScanStructByName(dest)
+ if err != nil {
+ return err
+ }
+ // Make sure the query can be processed to completion with no errors.
+ return row.rows.Close()
+}
+
+func (row *Row) ScanStructByIndex(dest interface{}) error {
+ if row.err != nil {
+ return row.err
+ }
+ defer row.rows.Close()
+
+ if !row.rows.Next() {
+ if err := row.rows.Err(); err != nil {
+ return err
+ }
+ return sql.ErrNoRows
+ }
+ err := row.rows.ScanStructByIndex(dest)
+ if err != nil {
+ return err
+ }
+ // Make sure the query can be processed to completion with no errors.
+ return row.rows.Close()
+}
+
+// scan data to a slice's pointer, slice's length should equal to columns' number
+func (row *Row) ScanSlice(dest interface{}) error {
+ if row.err != nil {
+ return row.err
+ }
+ defer row.rows.Close()
+
+ if !row.rows.Next() {
+ if err := row.rows.Err(); err != nil {
+ return err
+ }
+ return sql.ErrNoRows
+ }
+ err := row.rows.ScanSlice(dest)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the query can be processed to completion with no errors.
+ return row.rows.Close()
+}
+
+// scan data to a map's pointer
+func (row *Row) ScanMap(dest interface{}) error {
+ if row.err != nil {
+ return row.err
+ }
+ defer row.rows.Close()
+
+ if !row.rows.Next() {
+ if err := row.rows.Err(); err != nil {
+ return err
+ }
+ return sql.ErrNoRows
+ }
+ err := row.rows.ScanMap(dest)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the query can be processed to completion with no errors.
+ return row.rows.Close()
+}
+
+func (row *Row) ToMapString() (map[string]string, error) {
+ cols, err := row.Columns()
+ if err != nil {
+ return nil, err
+ }
+
+ var record = make(map[string]string, len(cols))
+ err = row.ScanMap(&record)
+ if err != nil {
+ return nil, err
+ }
+
+ return record, nil
+}