-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptions.go
196 lines (166 loc) · 5.6 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package http
import (
"fmt"
"net/url"
"reflect"
"strconv"
"strings"
"time"
)
// BackupOptions holds optional parameters for a backup operation.
type BackupOptions struct {
// Format can be "sql" if a SQL text dump is desired, otherwise an empty string
// (or something else) means a binary SQLite file is returned.
Format string `uvalue:"fmt"`
// If set, request that the backup be vacuumed before returning it.
Vacuum bool `uvalue:"vacuum"`
// If set, request that the backup be GZIP-compressed.
// e.g. /db/backup?compress
Compress bool `uvalue:"compress"`
// If set, ask a Follower not to forward the request to the Leader and instead
// read its local database and return that as the backup.
NoLeader bool `uvalue:"noleader"`
// If set, instruct a Follower to return a redirect instead of forwarding.
Redirect bool `uvalue:"redirect"`
}
// LoadOptions configures how to load data into the node.
type LoadOptions struct {
// Format can be "binary" or "sql" etc.
// - "binary" -> application/octet-stream
// - "sql" -> text/plain
Format string
// If set, instruct a Follower to return a redirect instead of forwarding.
// e.g. /db/load?redirect
Redirect bool
}
// BootOptions configures how to boot a single-node system.
type BootOptions struct {
// Potential expansions (for instance, forcing a redirect or not).
// Usually /boot is only relevant for a single-node system, so
// there's not too much to configure.
}
// ExecuteOptions holds optional settings for /db/execute requests.
type ExecuteOptions struct {
// Transaction indicates whether statements should be enclosed in a transaction.
Transaction bool `uvalue:"transaction,omitempty"`
// Pretty requests pretty-printed JSON.
Pretty bool `uvalue:"pretty,omitempty"`
// Timings requests timing information.
Timings bool `uvalue:"timings,omitempty"`
// Queue requests that the statement be queued
Queue bool `uvalue:"queue,omitempty"`
// Wait requests that the system only respond once the statement has been committed.
Wait bool `uvalue:"wait,omitempty"`
// Timeout after which if Wait is set, the system should respond with an error if
// the request has not been persisted.
Timeout time.Duration `uvalue:"timeout,omitempty"`
}
// QueryOptions holds optional settings for /db/query requests.
type QueryOptions struct {
// Timeout is applied at the database level.
Timeout time.Duration `uvalue:"timeout,omitempty"`
Pretty bool `uvalue:"pretty,omitempty"`
Timings bool `uvalue:"timings,omitempty"`
// Associative signals whether to request the "associative" form of results.
Associative bool `uvalue:"associative,omitempty"`
// BlobAsArray signals whether to request the BLOB data as arrays of byte values.
BlobAsArray bool `uvalue:"blob_array,omitempty"`
Level string `uvalue:"level,omitempty"`
LinearizableTimeout time.Duration `uvalue:"linearizable_timeout,omitempty"`
Freshness time.Duration `uvalue:"freshness,omitempty"`
FreshnessStrict bool `uvalue:"freshness_strict,omitempty"`
}
// RequestOptions holds optional settings for /db/request requests.
type RequestOptions struct {
// Transaction indicates whether statements should be enclosed in a transaction.
Transaction bool
// Timeout is applied at the database level.
Timeout string
Pretty bool
Timings bool
Associative bool
BlobAsArray bool
Level string // "weak" (default), "linearizable", "strong", "none", or "auto".
LinearizableTimeout string // e.g. "1s" if level=linearizable.
Freshness string // e.g. "1s" if level=none.
FreshnessStrict bool // if true, adds &freshness_strict.
}
// MakeURLValues converts a struct to a url.Values, using the `uvalue` tag to
// determine the key name.
func MakeURLValues(input any) (url.Values, error) {
vals := url.Values{}
if input == nil {
return vals, nil
}
val := reflect.ValueOf(input)
typ := reflect.TypeOf(input)
// If it's a pointer, get the underlying element.
if typ.Kind() == reflect.Ptr {
if val.IsNil() {
return vals, nil
}
val = val.Elem()
typ = typ.Elem()
}
if typ.Kind() != reflect.Struct {
return nil, fmt.Errorf("input must be a pointer to a struct, got %s", typ.Kind())
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tagVal := field.Tag.Get("uvalue")
if tagVal == "" {
// No `uvalue` tag, skip.
continue
}
parts := strings.Split(tagVal, ",")
tagVal = parts[0]
omitEmpty := false
if len(parts) > 1 {
// If there are multiple parts, the second part is the option.
omitEmpty = parts[1] == "omitempty"
}
fieldValue := val.Field(i)
if !fieldValue.CanInterface() {
// Unexported or inaccessible field.
continue
}
var strVal string
if fieldValue.Type() == reflect.TypeOf(time.Duration(0)) {
d := fieldValue.Interface().(time.Duration)
if d == 0 && omitEmpty {
continue
}
strVal = d.String()
} else {
switch fieldValue.Kind() {
case reflect.String:
strVal = fieldValue.Interface().(string)
if omitEmpty && strVal == "" {
continue
}
case reflect.Bool:
b := fieldValue.Interface().(bool)
if omitEmpty && !b {
continue
}
strVal = strconv.FormatBool(b)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i := fieldValue.Int()
if omitEmpty && i == 0 {
continue
}
strVal = strconv.FormatInt(i, 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
u := fieldValue.Uint()
if omitEmpty && u == 0 {
continue
}
strVal = strconv.FormatUint(u, 10)
default:
continue
}
}
vals.Add(tagVal, strVal)
}
return vals, nil
}