forked from marcboeker/go-duckdb
-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathvector_getters.go
More file actions
277 lines (236 loc) · 7.39 KB
/
vector_getters.go
File metadata and controls
277 lines (236 loc) · 7.39 KB
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
package duckdb
import (
"encoding/json"
"math/big"
"time"
"unsafe"
"github.com/duckdb/duckdb-go/v2/mapping"
)
// fnGetVectorValue is the getter callback function for any (nested) vector.
type fnGetVectorValue func(vec *vector, rowIdx mapping.IdxT) any
func (vec *vector) getNull(rowIdx mapping.IdxT) bool {
if vec.maskPtr == nil {
return false
}
return !mapping.ValidityMaskValueIsValid(vec.maskPtr, rowIdx)
}
func getPrimitive[T any](vec *vector, rowIdx mapping.IdxT) T {
var zero T
elementSize := unsafe.Sizeof(zero)
offset := uintptr(rowIdx) * elementSize
ptr := unsafe.Add(vec.dataPtr, offset)
return *(*T)(ptr)
}
func (vec *vector) getTS(t Type, rowIdx mapping.IdxT) time.Time {
switch t {
case TYPE_TIMESTAMP, TYPE_TIMESTAMP_TZ:
val := getPrimitive[mapping.Timestamp](vec, rowIdx)
return getTS(t, &val)
case TYPE_TIMESTAMP_S:
val := getPrimitive[mapping.TimestampS](vec, rowIdx)
return getTSS(&val)
case TYPE_TIMESTAMP_MS:
val := getPrimitive[mapping.TimestampMS](vec, rowIdx)
return getTSMS(&val)
case TYPE_TIMESTAMP_NS:
val := getPrimitive[mapping.TimestampNS](vec, rowIdx)
return getTSNS(&val)
default:
return time.Time{}
}
}
func getTS(t Type, ts *mapping.Timestamp) time.Time {
switch t {
case TYPE_TIMESTAMP, TYPE_TIMESTAMP_TZ:
return time.UnixMicro(mapping.TimestampMembers(ts)).UTC()
}
return time.Time{}
}
func getTSS(ts *mapping.TimestampS) time.Time {
return time.Unix(mapping.TimestampSMembers(ts), 0).UTC()
}
func getTSMS(ts *mapping.TimestampMS) time.Time {
return time.UnixMilli(mapping.TimestampMSMembers(ts)).UTC()
}
func getTSNS(ts *mapping.TimestampNS) time.Time {
return time.Unix(0, mapping.TimestampNSMembers(ts)).UTC()
}
func (vec *vector) getDate(rowIdx mapping.IdxT) time.Time {
date := getPrimitive[mapping.Date](vec, rowIdx)
return getDate(&date)
}
func getDate(date *mapping.Date) time.Time {
d := mapping.FromDate(*date)
year, month, day := mapping.DateStructMembers(&d)
return time.Date(int(year), time.Month(month), int(day), 0, 0, 0, 0, time.UTC)
}
func (vec *vector) getTime(rowIdx mapping.IdxT) time.Time {
switch vec.Type {
case TYPE_TIME:
val := getPrimitive[mapping.Time](vec, rowIdx)
return getTime(&val)
case TYPE_TIME_TZ:
ti := getPrimitive[mapping.TimeTZ](vec, rowIdx)
return getTimeTZ(&ti)
}
return time.Time{}
}
func getTime(ti *mapping.Time) time.Time {
micros := mapping.TimeMembers(ti)
unix := time.UnixMicro(micros).UTC()
return time.Date(1, time.January, 1, unix.Hour(), unix.Minute(), unix.Second(), unix.Nanosecond(), time.UTC)
}
func getTimeTZ(ti *mapping.TimeTZ) time.Time {
timeTZStruct := mapping.FromTimeTZ(*ti)
timeStruct, offset := mapping.TimeTZStructMembers(&timeTZStruct)
// TIMETZ has microsecond precision.
hour, minute, sec, micro := mapping.TimeStructMembers(&timeStruct)
nanos := int(micro) * 1000
loc := time.UTC
if offset != 0 {
loc = time.FixedZone("", int(offset))
}
return time.Date(1, time.January, 1, int(hour), int(minute), int(sec), nanos, loc)
}
func (vec *vector) getInterval(rowIdx mapping.IdxT) Interval {
interval := getPrimitive[mapping.Interval](vec, rowIdx)
return getInterval(&interval)
}
func getInterval(interval *mapping.Interval) Interval {
months, days, micros := mapping.IntervalMembers(interval)
return Interval{
Days: days,
Months: months,
Micros: micros,
}
}
func (vec *vector) getHugeint(rowIdx mapping.IdxT) *big.Int {
hugeInt := getPrimitive[mapping.HugeInt](vec, rowIdx)
return hugeIntToNative(&hugeInt)
}
func (vec *vector) getUhugeint(rowIdx mapping.IdxT) *big.Int {
uhugeInt := getPrimitive[mapping.UHugeInt](vec, rowIdx)
return uhugeIntToNative(&uhugeInt)
}
func (vec *vector) getBigNum(rowIdx mapping.IdxT) *big.Int {
// BIGNUM is stored as StringT containing DuckDB's encoding:
// - Bytes 0-2: 3-byte header (length | 0x800000 for positive, complemented for negative)
// - Bytes 3+: Big-endian magnitude (complemented for negative)
// Sign is determined by whether MSB of byte 0 is set (0x80)
strT := getPrimitive[mapping.StringT](vec, rowIdx)
data := []byte(mapping.StringTData(&strT))
if len(data) < 4 {
return big.NewInt(0)
}
// Check sign: MSB set means positive
isPositive := (data[0] & 0x80) != 0
// Data starts at byte 3, magnitude is already big-endian
magnitude := data[3:]
if isPositive {
return new(big.Int).SetBytes(magnitude)
}
// Negative: complement all magnitude bytes
complemented := make([]byte, len(magnitude))
for i := range magnitude {
complemented[i] = ^magnitude[i]
}
result := new(big.Int).SetBytes(complemented)
result.Neg(result)
return result
}
func (vec *vector) getBytes(rowIdx mapping.IdxT) any {
strT := getPrimitive[mapping.StringT](vec, rowIdx)
str := mapping.StringTData(&strT)
if vec.Type == TYPE_VARCHAR {
return str
}
return []byte(str)
}
func (vec *vector) getJSON(rowIdx mapping.IdxT) any {
bytes := vec.getBytes(rowIdx).(string)
var value any
_ = json.Unmarshal([]byte(bytes), &value)
return value
}
func (vec *vector) getDecimal(rowIdx mapping.IdxT) Decimal {
var val *big.Int
switch vec.internalType {
case TYPE_SMALLINT:
v := getPrimitive[int16](vec, rowIdx)
val = big.NewInt(int64(v))
case TYPE_INTEGER:
v := getPrimitive[int32](vec, rowIdx)
val = big.NewInt(int64(v))
case TYPE_BIGINT:
v := getPrimitive[int64](vec, rowIdx)
val = big.NewInt(v)
case TYPE_HUGEINT:
v := getPrimitive[mapping.HugeInt](vec, rowIdx)
val = hugeIntToNative(&v)
}
return Decimal{Width: vec.decimalWidth, Scale: vec.decimalScale, Value: val}
}
func (vec *vector) getEnum(rowIdx mapping.IdxT) string {
var idx mapping.IdxT
switch vec.internalType {
case TYPE_UTINYINT:
idx = mapping.IdxT(getPrimitive[uint8](vec, rowIdx))
case TYPE_USMALLINT:
idx = mapping.IdxT(getPrimitive[uint16](vec, rowIdx))
case TYPE_UINTEGER:
idx = mapping.IdxT(getPrimitive[uint32](vec, rowIdx))
case TYPE_UBIGINT:
idx = mapping.IdxT(getPrimitive[uint64](vec, rowIdx))
}
logicalType := mapping.VectorGetColumnType(vec.vec)
defer mapping.DestroyLogicalType(&logicalType)
return mapping.EnumDictionaryValue(logicalType, idx)
}
func (vec *vector) getList(rowIdx mapping.IdxT) []any {
entry := getPrimitive[mapping.ListEntry](vec, rowIdx)
offset, length := mapping.ListEntryMembers(&entry)
return vec.getSliceChild(offset, length)
}
func (vec *vector) getStruct(rowIdx mapping.IdxT) map[string]any {
m := map[string]any{}
for i := range vec.childVectors {
child := &vec.childVectors[i]
val := child.getFn(child, rowIdx)
m[vec.structEntries[i].Name()] = val
}
return m
}
func (vec *vector) getMap(rowIdx mapping.IdxT) OrderedMap {
list := vec.getList(rowIdx)
m := OrderedMap{}
for i := range list {
mapItem := list[i].(map[string]any)
key := mapItem[mapKeysField()]
val := mapItem[mapValuesField()]
m.Set(key, val)
}
return m
}
func (vec *vector) getArray(rowIdx mapping.IdxT) []any {
length := uint64(vec.arrayLength)
return vec.getSliceChild(uint64(rowIdx)*length, length)
}
func (vec *vector) getSliceChild(offset, length uint64) []any {
slice := make([]any, 0, length)
child := &vec.childVectors[0]
// Fill the slice with all child values.
for i := range length {
val := child.getFn(child, mapping.IdxT(i+offset))
slice = append(slice, val)
}
return slice
}
func (vec *vector) getUnion(rowIdx mapping.IdxT) any {
tag := getPrimitive[uint8](&vec.childVectors[0], rowIdx)
child := &vec.childVectors[tag+1]
value := child.getFn(child, rowIdx)
return Union{
Tag: vec.tagDict[uint32(tag)],
Value: value,
}
}