Skip to content

Commit 600ecc8

Browse files
committed
Merge branch 'feature/rethinkdb_v1.14' into develop
2 parents aed6a6f + 78c74f9 commit 600ecc8

File tree

12 files changed

+900
-374
lines changed

12 files changed

+900
-374
lines changed

datum.go

Lines changed: 0 additions & 79 deletions
This file was deleted.

pseudotypes.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package gorethink
2+
3+
import (
4+
"encoding/base64"
5+
"math"
6+
"strconv"
7+
"time"
8+
9+
"fmt"
10+
)
11+
12+
func convertPseudotype(obj map[string]interface{}, opts map[string]interface{}) (interface{}, error) {
13+
if reqlType, ok := obj["$reql_type$"]; ok {
14+
if reqlType == "TIME" {
15+
// load timeFormat, set to native if the option was not set
16+
timeFormat := "native"
17+
if opt, ok := opts["time_format"]; ok {
18+
if sopt, ok := opt.(string); ok {
19+
timeFormat = sopt
20+
} else {
21+
return nil, fmt.Errorf("Invalid time_format run option \"%s\".", opt)
22+
}
23+
}
24+
25+
if timeFormat == "native" {
26+
return reqlTimeToNativeTime(obj["epoch_time"].(float64), obj["timezone"].(string))
27+
} else if timeFormat == "raw" {
28+
return obj, nil
29+
} else {
30+
return nil, fmt.Errorf("Unknown time_format run option \"%s\".", reqlType)
31+
}
32+
} else if reqlType == "GROUPED_DATA" {
33+
// load groupFormat, set to native if the option was not set
34+
groupFormat := "native"
35+
if opt, ok := opts["group_format"]; ok {
36+
if sopt, ok := opt.(string); ok {
37+
groupFormat = sopt
38+
} else {
39+
return nil, fmt.Errorf("Invalid group_format run option \"%s\".", opt)
40+
}
41+
}
42+
43+
if groupFormat == "native" {
44+
return reqlGroupedDataToObj(obj)
45+
} else if groupFormat == "raw" {
46+
return obj, nil
47+
} else {
48+
return nil, fmt.Errorf("Unknown group_format run option \"%s\".", reqlType)
49+
}
50+
} else if reqlType == "BINARY" {
51+
binaryFormat := "native"
52+
if opt, ok := opts["binary_format"]; ok {
53+
if sopt, ok := opt.(string); ok {
54+
binaryFormat = sopt
55+
} else {
56+
return nil, fmt.Errorf("Invalid binary_format run option \"%s\".", opt)
57+
}
58+
}
59+
60+
if binaryFormat == "native" {
61+
return reqlBinaryToNativeBytes(obj)
62+
} else if binaryFormat == "raw" {
63+
return obj, nil
64+
} else {
65+
return nil, fmt.Errorf("Unknown binary_format run option \"%s\".", reqlType)
66+
}
67+
} else {
68+
return obj, nil
69+
}
70+
}
71+
72+
return obj, nil
73+
}
74+
75+
func recursivelyConvertPseudotype(obj interface{}, opts map[string]interface{}) (interface{}, error) {
76+
var err error
77+
78+
switch obj := obj.(type) {
79+
case []interface{}:
80+
for key, val := range obj {
81+
obj[key], err = recursivelyConvertPseudotype(val, opts)
82+
if err != nil {
83+
return nil, err
84+
}
85+
}
86+
case map[string]interface{}:
87+
for key, val := range obj {
88+
obj[key], err = recursivelyConvertPseudotype(val, opts)
89+
if err != nil {
90+
return nil, err
91+
}
92+
}
93+
94+
pobj, err := convertPseudotype(obj, opts)
95+
if err != nil {
96+
return nil, err
97+
}
98+
99+
return pobj, nil
100+
}
101+
102+
return obj, nil
103+
}
104+
105+
// Pseudo-type helper functions
106+
107+
func reqlTimeToNativeTime(timestamp float64, timezone string) (time.Time, error) {
108+
sec, ms := math.Modf(timestamp)
109+
110+
t := time.Unix(int64(sec), int64(ms*1000*1000*1000))
111+
112+
// Caclulate the timezone
113+
if timezone != "" {
114+
hours, err := strconv.Atoi(timezone[1:3])
115+
if err != nil {
116+
return time.Time{}, err
117+
}
118+
minutes, err := strconv.Atoi(timezone[4:6])
119+
if err != nil {
120+
return time.Time{}, err
121+
}
122+
tzOffset := ((hours * 60) + minutes) * 60
123+
if timezone[:1] == "-" {
124+
tzOffset = 0 - tzOffset
125+
}
126+
127+
t = t.In(time.FixedZone(timezone, tzOffset))
128+
}
129+
130+
return t, nil
131+
}
132+
133+
func reqlGroupedDataToObj(obj map[string]interface{}) (interface{}, error) {
134+
if data, ok := obj["data"]; ok {
135+
ret := []interface{}{}
136+
for _, v := range data.([]interface{}) {
137+
v := v.([]interface{})
138+
ret = append(ret, map[string]interface{}{
139+
"group": v[0],
140+
"reduction": v[1],
141+
})
142+
}
143+
return ret, nil
144+
} else {
145+
return nil, fmt.Errorf("pseudo-type GROUPED_DATA object %v does not have the expected field \"data\"", obj)
146+
}
147+
}
148+
149+
func reqlBinaryToNativeBytes(obj map[string]interface{}) (interface{}, error) {
150+
if data, ok := obj["data"]; ok {
151+
if data, ok := data.(string); ok {
152+
b, err := base64.StdEncoding.DecodeString(data)
153+
if err != nil {
154+
return nil, fmt.Errorf("error decoding pseudo-type BINARY object %v", obj)
155+
}
156+
157+
return b, nil
158+
} else {
159+
return nil, fmt.Errorf("pseudo-type BINARY object %v field \"data\" is not valid", obj)
160+
}
161+
} else {
162+
return nil, fmt.Errorf("pseudo-type BINARY object %v does not have the expected field \"data\"", obj)
163+
}
164+
}

0 commit comments

Comments
 (0)