From a618fd0c9cc35610d3cdf752dc4027cc83b62025 Mon Sep 17 00:00:00 2001 From: doun Date: Tue, 26 Feb 2013 19:20:07 +0800 Subject: [PATCH 1/5] add sqlite3 support, change base.go to support sqlite3 driver, not all tested --- base.go | 7 +++++- sqlite3.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 sqlite3.go diff --git a/base.go b/base.go index 639aec5..aa043f5 100644 --- a/base.go +++ b/base.go @@ -47,7 +47,12 @@ func (d *base) SetModelValue(driverValue, fieldValue reflect.Value) error { case reflect.Float32, reflect.Float64: fieldValue.SetFloat(driverValue.Elem().Float()) case reflect.String: - fieldValue.SetString(string(driverValue.Elem().Bytes())) + kind := reflect.TypeOf(driverValue.Elem()) + if _,ok := kind.FieldByName("val"); ok { + fieldValue.SetString(driverValue.Elem().String()) + }else { + fieldValue.SetString(string(driverValue.Elem().Bytes())) + } case reflect.Slice: if reflect.TypeOf(driverValue.Interface()).Elem().Kind() == reflect.Uint8 { fieldValue.SetBytes(driverValue.Elem().Bytes()) diff --git a/sqlite3.go b/sqlite3.go new file mode 100644 index 0000000..871c42c --- /dev/null +++ b/sqlite3.go @@ -0,0 +1,65 @@ +package hood + +import ( + "fmt" + "reflect" + "time" +) + +func init() { + RegisterDialect("sqlite3", NewSqlite3()) +} + +type sqlite3 struct { + base +} + +func NewSqlite3() Dialect { + d := &sqlite3{} + d.base.Dialect = d + return d +} + +func (d *sqlite3) NextMarker(pos *int) string { + return "?" +} + +func (d *sqlite3) Quote(s string) string { + return fmt.Sprintf("`%s`", s) +} + +func (d *sqlite3) ParseBool(value reflect.Value) bool { + return value.Int() != 0 +} + +func (d *sqlite3) SqlType(f interface{}, size int) string { + switch f.(type) { + case Id: + return "INTEGER" + case time.Time, Created, Updated: + return "timestamp" + case bool: + return "boolean" + case int, int8, int16, int32, uint, uint8, uint16, uint32: + return "int" + case int64, uint64: + return "bigint" + case float32, float64: + return "double" + case []byte: + if size > 0 && size < 65532 { + return fmt.Sprintf("varbinary(%d)", size) + } + return "longblob" + case string: + if size > 0 && size < 65532 { + return fmt.Sprintf("varchar(%d)", size) + } + return "longtext" + } + panic("invalid sql type") +} + +func (d *sqlite3) KeywordAutoIncrement() string { + return "AUTOINCREMENT" +} From 2592365a30ae9714cc15eafeeea839f01d8dad04 Mon Sep 17 00:00:00 2001 From: doun Date: Tue, 16 Apr 2013 00:19:47 +0800 Subject: [PATCH 2/5] try to add findone, and copy/modify findsql to create a findsqlone func --- hood.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/hood.go b/hood.go index ea3f16e..25db2e7 100644 --- a/hood.go +++ b/hood.go @@ -680,6 +680,70 @@ func (hood *Hood) Find(out interface{}) error { query, args := hood.Dialect.QuerySql(hood) return hood.FindSql(out, query, args...) } +func (hood *Hood) FindOne(out interface{})error{ + if hood.selectTable == ""{ + hood.Select(out) + } + query, args := hood.Dialect.QuerySql(hood) + return hood.FindOneSql(out,query,args...) +} +func (hood *Hood) FindOneSql(out interface{}, query string, args ...interface{}) error { + hood.mutex.Lock() + defer hood.mutex.Unlock() + defer hood.Reset() + + panicMsg := errors.New("expected pointer to struct") + if x := reflect.TypeOf(out).Kind(); x != reflect.Ptr { + panic(panicMsg) + } + outValue := reflect.Indirect(reflect.ValueOf(out)) + if x := outValue.Kind(); x != reflect.Struct { + panic(panicMsg) + } + hood.logSql(query, args...) + stmt, err := hood.qo.Prepare(query) + if err != nil { + return hood.updateTxError(err) + } + defer stmt.Close() + rows, err := stmt.Query(args...) + if err != nil { + return hood.updateTxError(err) + } + defer rows.Close() + cols, err := rows.Columns() + if err != nil { + return hood.updateTxError(err) + } + for rows.Next() { + containers := make([]interface{}, 0, len(cols)) + for i := 0; i < cap(containers); i++ { + var v interface{} + containers = append(containers, &v) + } + err := rows.Scan(containers...) + if err != nil { + return err + } + // create a new row and fill + rowValue := reflect.New(reflect.TypeOf(outValue)) + for i, v := range containers { + key := cols[i] + value := reflect.Indirect(reflect.ValueOf(v)) + name := snakeToUpperCamel(key) + field := rowValue.Elem().FieldByName(name) + if field.IsValid() { + err = hood.Dialect.SetModelValue(value, field) + if err != nil { + return err + } + } + } + outValue.Set(rowValue) + break; + } + return nil +} // FindSql performs a find using the specified custom sql query and arguments and // writes the results to the specified out interface{}. From f85c7c84fe7661ca3415641d602d0cab5e6fe306 Mon Sep 17 00:00:00 2001 From: doun Date: Tue, 16 Apr 2013 07:50:19 +0800 Subject: [PATCH 3/5] not finished --- hood.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hood.go b/hood.go index 25db2e7..e104716 100644 --- a/hood.go +++ b/hood.go @@ -683,6 +683,7 @@ func (hood *Hood) Find(out interface{}) error { func (hood *Hood) FindOne(out interface{})error{ if hood.selectTable == ""{ hood.Select(out) + hood.Limit(1) } query, args := hood.Dialect.QuerySql(hood) return hood.FindOneSql(out,query,args...) @@ -696,8 +697,9 @@ func (hood *Hood) FindOneSql(out interface{}, query string, args ...interface{}) if x := reflect.TypeOf(out).Kind(); x != reflect.Ptr { panic(panicMsg) } - outValue := reflect.Indirect(reflect.ValueOf(out)) - if x := outValue.Kind(); x != reflect.Struct { + outValue := reflect.ValueOf(out).Elem() + outRef := reflect.Indirect(outValue) + if x := outRef.Kind(); x != reflect.Struct { panic(panicMsg) } hood.logSql(query, args...) @@ -739,7 +741,7 @@ func (hood *Hood) FindOneSql(out interface{}, query string, args ...interface{}) } } } - outValue.Set(rowValue) + outValue.Set(reflect.Indirect(rowValue)) break; } return nil From 5f7f32afa0de66ab986cbfa14940666ac670a0c6 Mon Sep 17 00:00:00 2001 From: doun Date: Tue, 16 Apr 2013 11:24:05 +0800 Subject: [PATCH 4/5] may be finished. --- hood.go | 72 ++++++++++----------------------------------------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/hood.go b/hood.go index e104716..b6ef14a 100644 --- a/hood.go +++ b/hood.go @@ -680,71 +680,23 @@ func (hood *Hood) Find(out interface{}) error { query, args := hood.Dialect.QuerySql(hood) return hood.FindSql(out, query, args...) } -func (hood *Hood) FindOne(out interface{})error{ - if hood.selectTable == ""{ - hood.Select(out) - hood.Limit(1) - } - query, args := hood.Dialect.QuerySql(hood) - return hood.FindOneSql(out,query,args...) -} -func (hood *Hood) FindOneSql(out interface{}, query string, args ...interface{}) error { - hood.mutex.Lock() - defer hood.mutex.Unlock() - defer hood.Reset() - - panicMsg := errors.New("expected pointer to struct") +func (hood *Hood) FindOne(out interface{}) error { + hood.Limit(1) + panicMsg := errors.New("expected pointer to struct slice") if x := reflect.TypeOf(out).Kind(); x != reflect.Ptr { panic(panicMsg) } - outValue := reflect.ValueOf(out).Elem() - outRef := reflect.Indirect(outValue) - if x := outRef.Kind(); x != reflect.Struct { + ptrVal := reflect.Indirect(reflect.ValueOf(out)) + if x := ptrVal.Kind(); x != reflect.Struct { panic(panicMsg) } - hood.logSql(query, args...) - stmt, err := hood.qo.Prepare(query) - if err != nil { - return hood.updateTxError(err) - } - defer stmt.Close() - rows, err := stmt.Query(args...) - if err != nil { - return hood.updateTxError(err) - } - defer rows.Close() - cols, err := rows.Columns() - if err != nil { - return hood.updateTxError(err) - } - for rows.Next() { - containers := make([]interface{}, 0, len(cols)) - for i := 0; i < cap(containers); i++ { - var v interface{} - containers = append(containers, &v) - } - err := rows.Scan(containers...) - if err != nil { - return err - } - // create a new row and fill - rowValue := reflect.New(reflect.TypeOf(outValue)) - for i, v := range containers { - key := cols[i] - value := reflect.Indirect(reflect.ValueOf(v)) - name := snakeToUpperCamel(key) - field := rowValue.Elem().FieldByName(name) - if field.IsValid() { - err = hood.Dialect.SetModelValue(value, field) - if err != nil { - return err - } - } - } - outValue.Set(reflect.Indirect(rowValue)) - break; - } - return nil + sType := reflect.MakeSlice(reflect.SliceOf(ptrVal.Type()), 0, 0) + pSlice := reflect.New(sType.Type()).Interface() + err := hood.Find(pSlice) + found := reflect.Indirect(reflect.ValueOf(pSlice)).Index(0).Interface() + reflect.ValueOf(out).Elem().Set(reflect.ValueOf(found)) + + return err } // FindSql performs a find using the specified custom sql query and arguments and From 25e4d1d4384646a8ed55200f2c42d25eb151b518 Mon Sep 17 00:00:00 2001 From: doun Date: Tue, 16 Apr 2013 15:59:31 +0800 Subject: [PATCH 5/5] fix mysql drv string val err. shoud be ok for others? --- base.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/base.go b/base.go index aa043f5..8e5e1ab 100644 --- a/base.go +++ b/base.go @@ -47,12 +47,14 @@ func (d *base) SetModelValue(driverValue, fieldValue reflect.Value) error { case reflect.Float32, reflect.Float64: fieldValue.SetFloat(driverValue.Elem().Float()) case reflect.String: - kind := reflect.TypeOf(driverValue.Elem()) - if _,ok := kind.FieldByName("val"); ok { - fieldValue.SetString(driverValue.Elem().String()) - }else { - fieldValue.SetString(string(driverValue.Elem().Bytes())) - } + //shoud be string(...) + fieldValue.SetString(string(driverValue.Elem().Bytes())) + // kind := reflect.TypeOf(driverValue.Elem()) + // if _,ok := kind.FieldByName("val"); ok { + // fieldValue.SetString(string(driverValue.Elem().Bytes())) + // }else { + // fieldValue.SetString(string(driverValue.Elem().Bytes())) + // } case reflect.Slice: if reflect.TypeOf(driverValue.Interface()).Elem().Kind() == reflect.Uint8 { fieldValue.SetBytes(driverValue.Elem().Bytes())