github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/big_query/chart_struct_save_and_retrieve.go (about) 1 package big_query 2 3 import ( 4 "bytes" 5 "encoding/gob" 6 "fmt" 7 "net/http" 8 9 "github.com/pbberlin/tools/dsu" 10 "github.com/pbberlin/tools/net/http/loghttp" 11 "google.golang.org/appengine" 12 ) 13 14 // Chart data 15 // 16 // Normally, datastore types are restricted. 17 // For intstance a 18 // map[string]map[string]float64 19 // can not be a datastore field. 20 // 21 // Therefore, this package takes a complex struct 22 // and *globs* it into a byte array, 23 // quasi normalizing it. 24 // 25 // It then saves the byte array within a dsu.WrapBlob 26 // 27 // This way, any struct can be saved into into datastore 28 // using dsu.WrapBlob. 29 type CData struct { 30 M map[string]map[string]float64 31 VPeriods []string 32 VLangs []string 33 F_max float64 34 unexported string 35 } 36 37 // http://stackoverflow.com/questions/12854125/go-how-do-i-dump-the-struct-into-the-byte-array-without-reflection 38 39 func SaveChartDataToDatastore(w http.ResponseWriter, r *http.Request, cd CData, key string) string { 40 41 c := appengine.NewContext(r) 42 43 internalType := fmt.Sprintf("%T", cd) 44 //buffBytes, _ := StringToVByte(s) // instead of []byte(s) 45 46 // CData to []byte 47 serializedStruct := new(bytes.Buffer) 48 enc := gob.NewEncoder(serializedStruct) 49 err := enc.Encode(cd) 50 loghttp.E(w, r, err, false) 51 52 key_combi, err := dsu.BufPut(c, 53 dsu.WrapBlob{Name: key, VByte: serializedStruct.Bytes(), S: internalType}, key) 54 loghttp.E(w, r, err, false) 55 56 return key_combi 57 } 58 59 func GetChartDataFromDatastore(w http.ResponseWriter, r *http.Request, key string) *CData { 60 61 c := appengine.NewContext(r) 62 63 key_combi := "dsu.WrapBlob__" + key 64 65 dsObj, err := dsu.BufGet(c, key_combi) 66 loghttp.E(w, r, err, false) 67 68 serializedStruct := bytes.NewBuffer(dsObj.VByte) 69 dec := gob.NewDecoder(serializedStruct) 70 newCData := new(CData) // hell, it was set to nil above - causing this "unassignable value" error 71 err = dec.Decode(newCData) 72 loghttp.E(w, r, err, false, "VByte was ", dsObj.VByte[:10]) 73 74 return newCData 75 } 76 77 func testGobDecodeEncode(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { 78 79 c := appengine.NewContext(r) 80 81 nx := 24 82 83 // without custom implementation 84 // everything is encoded/decoded except field unexported 85 orig := CData{ 86 M: map[string]map[string]float64{"lang1": map[string]float64{"2012-09": 0.2}}, 87 VPeriods: []string{"2011-11", "2014-11"}, 88 VLangs: []string{"C", "++"}, 89 F_max: 44.2, 90 unexported: "val of unexported", 91 } 92 fmt.Fprintf(w, "orig\n%#v\n", &orig) 93 94 // writing to []byte 95 serializedStruct := new(bytes.Buffer) 96 enc := gob.NewEncoder(serializedStruct) 97 err := enc.Encode(orig) 98 loghttp.E(w, r, err, false) 99 100 sx := serializedStruct.String() 101 lx := len(sx) 102 fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:]) 103 104 // saving to ds 105 key_combi, err := dsu.BufPut(c, 106 dsu.WrapBlob{Name: "chart_data_test_1", VByte: serializedStruct.Bytes(), S: "chart data"}, "chart_data_test_1") 107 loghttp.E(w, r, err, false) 108 // restoring from ds 109 dsObj, err := dsu.BufGet(c, key_combi) 110 loghttp.E(w, r, err, false) 111 112 p := r.FormValue("p") 113 114 // reading 115 rest1 := new(CData) 116 if p == "" { 117 sx := string(dsObj.VByte) 118 lx := len(sx) 119 fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:]) 120 121 readr := bytes.NewBuffer(dsObj.VByte) 122 dec := gob.NewDecoder(readr) 123 err = dec.Decode(rest1) 124 loghttp.E(w, r, err, false) 125 } else { 126 readr := bytes.NewBuffer(serializedStruct.Bytes()) 127 dec := gob.NewDecoder(readr) 128 err = dec.Decode(rest1) 129 loghttp.E(w, r, err, false) 130 } 131 132 fmt.Fprintf(w, "resl\n%#v\n", rest1) 133 134 fmt.Fprintf(w, "\n\n") 135 SaveChartDataToDatastore(w, r, orig, "chart_data_test_2") 136 137 dsObj2, err := dsu.BufGet(c, "dsu.WrapBlob__chart_data_test_2") 138 loghttp.E(w, r, err, false) 139 { 140 141 rest2 := new(CData) 142 143 sx := string(dsObj2.VByte) 144 lx := len(sx) 145 fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:]) 146 147 readr := bytes.NewBuffer(dsObj2.VByte) 148 dec := gob.NewDecoder(readr) 149 err = dec.Decode(rest2) 150 loghttp.E(w, r, err, false) 151 152 fmt.Fprintf(w, "res2\n%#v\n", rest2) 153 154 } 155 156 f1 := GetChartDataFromDatastore(w, r, "chart_data_test_2") 157 fmt.Fprintf(w, "resl\n%#v\n", f1) 158 159 } 160 161 // if we wanted to gob.Encode/Decode unexported fields, 162 // like CData.unexported, then we have to implement 163 // every field ourselves 164 // => uncomment following ... 165 /* 166 func (d *CData)GobEncode() ([]byte, error) { 167 w := new(bytes.Buffer) 168 encoder := gob.NewEncoder(w) 169 err := encoder.Encode(d.unexported) 170 if err!=nil { return nil, err } 171 return w.Bytes(), nil 172 } 173 174 func (d *CData)GobDecode(buf []byte) error { 175 r := bytes.NewBuffer(buf) 176 decoder := gob.NewDecoder(r) 177 return decoder.Decode(&d.unexported) 178 } 179 */