package sqlite import ( "fmt" "strings" "github.com/spf13/cast" "github.com/wecisecode/util/msgpack" ) func BlobMarshal(v interface{}) (s string) { bs, e := msgpack.Encode(v) if e != nil { t, e := cast.ToStringE(v) if e != nil { s = fmt.Sprintf("%#v", v) } s = t } else { s = string(bs) } return } func SliceTypeRecognize(tx []interface{}) (v interface{}, t string) { t = "" for _, a := range tx { switch a.(type) { case string: if t == "" { t = "string" } if t != "string" { t = "" break } case int: if t == "" { t = "int" } if t != "int" { t = "" break } } } switch t { case "string": tss := make([]string, len(tx)) for i, a := range tx { tss[i] = cast.ToString(a) } v = tss case "int": tis := make([]int, len(tx)) for i, a := range tx { tis[i] = cast.ToInt(a) } v = tis default: v = tx } return } func MapTypeRecognize(tx map[string]interface{}) (v interface{}, t string) { t = "" tvs := map[string]interface{}{} for k, a := range tx { switch ta := a.(type) { case []interface{}: av, at := SliceTypeRecognize(ta) if t == "" { t = "[]" + at } if t != "[]"+at { t = "" break } tvs[k] = av case []string: if t == "" { t = "[]string" } if t != "[]string" { t = "" break } tvs[k] = ta case []int: if t == "" { t = "[]int" } if t != "[]int" { t = "" break } tvs[k] = ta case string: if t == "" { t = "string" } if t != "string" { t = "" break } tvs[k] = ta case int: if t == "" { t = "int" } if t != "int" { t = "" break } tvs[k] = ta } } switch t { case "[]string": tss := make(map[string][]string, len(tx)) for i, a := range tvs { tss[i] = cast.ToStringSlice(a) } v = tss case "[]int": tis := make(map[string][]int, len(tx)) for i, a := range tvs { tis[i] = cast.ToIntSlice(a) } v = tis case "string": tss := make(map[string]string, len(tx)) for i, a := range tvs { tss[i] = cast.ToString(a) } v = tss case "int": tis := make(map[string]int, len(tx)) for i, a := range tvs { tis[i] = cast.ToInt(a) } v = tis default: v = tx } return } func MapsTypeRecognize(tx []map[string]interface{}) (v interface{}, t string) { t = "" tvs := []interface{}{} for _, x := range tx { av, at := MapTypeRecognize(x) if t == "" { t = at } if t != at { t = "" break } tvs = append(tvs, av) } switch t { case "[]string": tss := make([]map[string][]string, len(tx)) for i, a := range tvs { tss[i] = a.(map[string][]string) } v = tss case "[]int": tis := make([]map[string][]int, len(tx)) for i, a := range tvs { tis[i] = a.(map[string][]int) } v = tis case "string": tss := make([]map[string]string, len(tx)) for i, a := range tvs { tss[i] = a.(map[string]string) } v = tss case "int": tis := make([]map[string]int, len(tx)) for i, a := range tvs { tis[i] = a.(map[string]int) } v = tis default: v = tx } return } func BlobRecognize(x interface{}) (v interface{}, t string) { v = x switch tx := x.(type) { case []map[string]interface{}: v, t = MapsTypeRecognize(tx) case map[string]interface{}: v, t = MapTypeRecognize(tx) case []interface{}: v, t = SliceTypeRecognize(tx) case *interface{}: v, t = BlobRecognize(*tx) default: v = tx } return } func BlobUnmarshal(s string, x interface{}) (v interface{}) { e := msgpack.Decode([]byte(s), x) if e != nil { return s } v = x return } // 从 sqlite 读出的数据 到 go 语言中 func SQLValueDecode(ftype_sampledata, value interface{}) (v interface{}) { v = value switch ftype := ftype_sampledata.(type) { case string: switch ftype { case "BOOL", "BOOLEAN": v = cast.ToBool(v) case "BLOB": s := cast.ToString(v) var x interface{} v = BlobUnmarshal(s, &x) v, _ = BlobRecognize(v) case "INT", "INTEGER": switch tv := v.(type) { case int8: v = int(tv) case int16: v = int(tv) case int32: v = int(tv) case int64: v = int(tv) case uint: v = int(tv) case uint8: v = int(tv) case uint16: v = int(tv) case uint32: v = int(tv) case uint64: v = int(tv) } case "DATE": // 兼容cassandra输出 v = cast.ToTime(v) case "TIME", "DATETIME", "TIMESTAMP": v = NSTimeStampValue(v) } return } s := cast.ToString(v) v = BlobUnmarshal(s, ftype_sampledata) return } // 从 go 语言数据 到 sqlite 数据库中 func SQLValueEncode(ftype string, v interface{}) interface{} { if v == nil { return nil } switch strings.ToLower(ftype) { case "int", "integer": return cast.ToInt(v) case "long", "bigint", "int64": return cast.ToInt64(v) case "int32": return cast.ToInt32(v) case "enum", "smallint", "int16": return cast.ToInt16(v) case "double", "float64": return cast.ToFloat64(v) case "float", "float32": return cast.ToFloat32(v) case "bool", "boolean": return cast.ToBool(v) case "string", "text", "varchar", "clob": return cast.ToString(v) case "date": return MSTimeStampValue(v).Format("2006-01-02") case "time", "datetime", "timestamp": return MSTimeStampValue(v).UnixNano() case "relation": sv := BlobMarshal(v) if sv == "{}" { // 兼容cassandra输入 sv = "null" } return sv case "blob", "map", "list", "set", "bucket": fallthrough default: return BlobMarshal(v) } }