diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..081b737
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 数据源本地存储已忽略文件
+/dataSources/
+/dataSources.local.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..fc80dce
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/stardb.iml b/.idea/stardb.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/stardb.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/orm_v1.go b/orm_v1.go
new file mode 100644
index 0000000..ea09c06
--- /dev/null
+++ b/orm_v1.go
@@ -0,0 +1,93 @@
+package stardb
+
+import (
+ "database/sql"
+ "errors"
+ "reflect"
+ "strings"
+)
+
+func (star *StarRows) Orm(ins interface{}) error {
+ //check if is slice
+ if !star.parsed {
+ if err := star.parserows(); err != nil {
+ return err
+ }
+ }
+ t := reflect.TypeOf(ins)
+ v := reflect.ValueOf(ins)
+ if t.Kind() != reflect.Ptr {
+ return errors.New("interface not writable")
+ }
+ //now convert to slice
+ t = t.Elem()
+ v = v.Elem()
+ if star.Length == 0 {
+ return nil
+ }
+ if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
+ //get type of slice
+ sigType := t.Elem()
+ var result reflect.Value
+ result = reflect.New(t).Elem()
+ for i := 0; i < star.Length; i++ {
+ val := reflect.New(sigType)
+ star.setAllRefValue(val.Interface(), "db", i)
+ result = reflect.Append(result, val.Elem())
+ }
+ v.Set(result)
+ return nil
+ }
+
+ return star.setAllRefValue(ins, "db", 0)
+}
+
+func (star *StarDB) QueryX(sql string, ins interface{}, args ...interface{}) (*StarRows, error) {
+ kvMap, err := getAllRefValue(ins, "db")
+ if err != nil {
+ return nil, err
+ }
+ for k, v := range args {
+ switch v.(type) {
+ case string:
+ str := v.(string)
+ if strings.Index(str, ":") == 0 {
+ if _, ok := kvMap[str[1:]]; ok {
+ args[k] = kvMap[str[1:]]
+ } else {
+ args[k] = ""
+ }
+ continue
+ }
+ if strings.Index(str, `\:`) == 0 {
+ args[k] = kvMap[str[1:]]
+ }
+ }
+ }
+ return star.Query(sql, args)
+}
+
+func (star *StarDB) ExecX(sql string, ins interface{}, args ...interface{}) (sql.Result, error) {
+ kvMap, err := getAllRefValue(ins, "db")
+ if err != nil {
+ return nil, err
+ }
+ for k, v := range args {
+ switch v.(type) {
+ case string:
+ str := v.(string)
+ if strings.Index(str, ":") == 0 {
+ if _, ok := kvMap[str[1:]]; ok {
+ args[k] = kvMap[str[1:]]
+ } else {
+ args[k] = ""
+ }
+ continue
+ }
+ if strings.Index(str, `\:`) == 0 {
+ args[k] = kvMap[str[1:]]
+ }
+ }
+ }
+ return star.Exec(sql, args)
+}
diff --git a/reflect.go b/reflect.go
new file mode 100644
index 0000000..021abbd
--- /dev/null
+++ b/reflect.go
@@ -0,0 +1,162 @@
+package stardb
+
+import (
+ "errors"
+ "reflect"
+)
+
+func (star *StarRows) setAllRefValue(stc interface{}, skey string, rows int) error {
+ t := reflect.TypeOf(stc)
+ v := reflect.ValueOf(stc).Elem()
+ if t.Kind() != reflect.Ptr || !v.CanSet() {
+ return errors.New("interface{} is not writable")
+ }
+ if v.Kind() != reflect.Struct {
+ return errors.New("interface{} is not a struct")
+ }
+ t = t.Elem()
+ for i := 0; i < t.NumField(); i++ {
+ tp := t.Field(i)
+ seg := tp.Tag.Get(skey)
+ if seg == "" {
+ continue
+ }
+ if _, ok := star.Row(rows).columnref[seg]; !ok {
+ continue
+ }
+ myInt64 := star.Row(rows).MustInt64(seg)
+ myUint64 := uint64(star.Row(rows).MustInt64(seg))
+ switch v.Field(i).Kind() {
+ case reflect.String:
+ v.Field(i).SetString(star.Row(rows).MustString(seg))
+ case reflect.Int64:
+ v.Field(i).SetInt(myInt64)
+ case reflect.Int32:
+ v.Field(i).SetInt(int64(star.Row(rows).MustInt32(seg)))
+ case reflect.Int16:
+ v.Field(i).SetInt(int64(int16(myInt64)))
+ case reflect.Int8:
+ v.Field(i).SetInt(int64(int8(myInt64)))
+ case reflect.Uint64:
+ v.Field(i).SetUint(myUint64)
+ case reflect.Uint32:
+ v.Field(i).SetUint(uint64(uint32(myUint64)))
+ case reflect.Uint16:
+ v.Field(i).SetUint(uint64(uint16(myUint64)))
+ case reflect.Uint8:
+ v.Field(i).SetUint(uint64(uint8(myUint64)))
+ case reflect.Bool:
+ v.Field(i).SetBool(star.Row(rows).MustBool(seg))
+ case reflect.Float64:
+ v.Field(i).SetFloat(star.Row(rows).MustFloat64(seg))
+ case reflect.Float32:
+ v.Field(i).SetFloat(float64(star.Row(rows).MustFloat32(seg)))
+ default:
+ }
+
+ }
+ return nil
+}
+
+func setAllRefValue(stc interface{}, skey string, kv map[string]interface{}) error {
+ t := reflect.TypeOf(stc)
+ v := reflect.ValueOf(stc).Elem()
+ if t.Kind() != reflect.Ptr || !v.CanSet() {
+ return errors.New("interface{} is not writable")
+ }
+ if v.Kind() != reflect.Struct {
+ return errors.New("interface{} is not a struct")
+ }
+ t = t.Elem()
+ for i := 0; i < t.NumField(); i++ {
+ tp := t.Field(i)
+ seg := tp.Tag.Get(skey)
+ if seg == "" {
+ continue
+ }
+ if _, ok := kv[seg]; !ok {
+ continue
+ }
+ v.Field(i).Set(reflect.ValueOf(kv[seg]))
+ }
+ return nil
+}
+
+func setRefValue(stc interface{}, skey, key string, value interface{}) error {
+ t := reflect.TypeOf(stc)
+ v := reflect.ValueOf(stc).Elem()
+ if t.Kind() != reflect.Ptr || !v.CanSet() {
+ return errors.New("interface{} is not writable")
+ }
+ if v.Kind() != reflect.Struct {
+ return errors.New("interface{} is not a struct")
+ }
+ t = t.Elem()
+ for i := 0; i < t.NumField(); i++ {
+ tp := t.Field(i)
+ seg := tp.Tag.Get(skey)
+ if seg == "" || key != seg {
+ continue
+ }
+ v.Field(i).Set(reflect.ValueOf(value))
+ }
+ return nil
+}
+
+func getAllRefValue(stc interface{}, skey string) (map[string]interface{}, error) {
+ result := make(map[string]interface{})
+ t := reflect.TypeOf(stc)
+ v := reflect.ValueOf(stc)
+ if v.Kind() != reflect.Struct {
+ return nil, errors.New("interface{} is not a struct")
+ }
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ v = v.Elem()
+ }
+ for i := 0; i < t.NumField(); i++ {
+ tp := t.Field(i)
+ seg := tp.Tag.Get(skey)
+ if seg == "" {
+ continue
+ }
+ value := v.Field(i)
+ if !value.CanInterface() {
+ continue
+ }
+ result[seg] = value.Interface()
+ }
+ return result, nil
+}
+
+func getAllRefKey(stc interface{}, skey string) ([]string, error) {
+ var result []string
+ _, isStruct := isWritableStruct(stc)
+ if !isStruct {
+ return []string{}, errors.New("interface{} is not a struct")
+ }
+ t := reflect.TypeOf(stc)
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ for i := 0; i < t.NumField(); i++ {
+ profile := t.Field(i)
+ seg := profile.Tag.Get(skey)
+ if seg != "" {
+ result = append(result, seg)
+ }
+ }
+ return result, nil
+}
+
+func isWritableStruct(stc interface{}) (isWritable bool, isStruct bool) {
+ t := reflect.TypeOf(stc)
+ v := reflect.ValueOf(stc)
+ if t.Kind() == reflect.Ptr && v.Elem().CanSet() {
+ isWritable = true
+ }
+ if v.Kind() == reflect.Struct {
+ isStruct = true
+ }
+ return
+}
diff --git a/reflect_test.go b/reflect_test.go
new file mode 100644
index 0000000..9445aad
--- /dev/null
+++ b/reflect_test.go
@@ -0,0 +1,44 @@
+package stardb
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+type Useless struct {
+ Leader string `db:"leader"`
+ Usable bool `db:"use"`
+}
+
+func Test_SetRefVal(t *testing.T) {
+ var hehe = Useless{
+ Leader: "no",
+ }
+ mmval := map[string]interface{}{
+ "leader": "hehe",
+ "use": true,
+ }
+ fmt.Printf("%+v\n", hehe)
+ fmt.Println(setRefValue(&hehe, "db", "leader", "sb"))
+ fmt.Printf("%+v\n", hehe)
+ fmt.Println(setAllRefValue(&hehe, "db", mmval))
+ fmt.Printf("%+v\n", hehe)
+ fmt.Println(getAllRefKey(hehe, "db"))
+}
+
+func Test_Ref(t *testing.T) {
+ var me []Useless
+ p := reflect.TypeOf(&me).Elem()
+ v := reflect.ValueOf(&me).Elem()
+ mmval := map[string]interface{}{
+ "leader": "hehe",
+ "use": true,
+ }
+ newVal := reflect.New(p)
+ val := reflect.New(p.Elem())
+ setAllRefValue(val.Interface(), "db", mmval)
+ mynum:= reflect.Append(newVal.Elem(), val.Elem())
+ v.Set(mynum)
+ fmt.Println(val.Interface(), me, v)
+}
diff --git a/stardb_v1.go b/stardb_v1.go
index 842f452..4db6e5f 100644
--- a/stardb_v1.go
+++ b/stardb_v1.go
@@ -10,8 +10,8 @@ import (
// StarDB 一个简单封装的DB库
type StarDB struct {
- DB *sql.DB
- Rows *sql.Rows
+ DB *sql.DB
+ ManualScan bool
}
// StarRows 为查询结果集(按行)
@@ -23,6 +23,7 @@ type StarRows struct {
ColumnsType []reflect.Type
columnref map[string]int
result [][]interface{}
+ parsed bool
}
// StarResult 为查询结果集(总)
@@ -674,7 +675,10 @@ func (star *StarRows) Close() error {
return star.Rows.Close()
}
-func (star *StarRows) parserows() {
+func (star *StarRows) parserows() error {
+ defer func() {
+ star.parsed = true
+ }()
star.result = [][]interface{}{}
star.columnref = make(map[string]int)
star.StringResult = []map[string]string{}
@@ -691,7 +695,7 @@ func (star *StarRows) parserows() {
}
for star.Rows.Next() {
if err := star.Rows.Scan(scanArgs...); err != nil {
- return
+ return err
}
record := make(map[string]string)
var rescopy []interface{}
@@ -724,11 +728,13 @@ func (star *StarRows) parserows() {
star.StringResult = append(star.StringResult, record)
}
star.Length = len(star.StringResult)
+ return nil
}
// Query 进行Query操作
func (star *StarDB) Query(args ...interface{}) (*StarRows, error) {
var err error
+ var rows *sql.Rows
effect := new(StarRows)
if err = star.DB.Ping(); err != nil {
return effect, err
@@ -738,10 +744,10 @@ func (star *StarDB) Query(args ...interface{}) (*StarRows, error) {
}
if len(args) == 1 {
sql := args[0]
- if star.Rows, err = star.DB.Query(sql.(string)); err != nil {
+ if rows, err = star.DB.Query(sql.(string)); err != nil {
return effect, err
}
- effect.Rows = star.Rows
+ effect.Rows = rows
effect.parserows()
return effect, nil
}
@@ -760,12 +766,14 @@ func (star *StarDB) Query(args ...interface{}) (*StarRows, error) {
}
}
}
- if star.Rows, err = stmt.Query(para...); err != nil {
+ if rows, err = stmt.Query(para...); err != nil {
return effect, err
}
- effect.Rows = star.Rows
- effect.parserows()
- return effect, nil
+ effect.Rows = rows
+ if !star.ManualScan {
+ err = effect.parserows()
+ }
+ return effect, err
}
// Open 打开一个新的数据库