@@ -2,11 +2,11 @@ package array
2
2
3
3
import (
4
4
"strconv"
5
- "sync/atomic"
6
5
7
6
"github.com/apache/arrow/go/v7/arrow"
8
7
"github.com/apache/arrow/go/v7/arrow/array"
9
8
arrowmem "github.com/apache/arrow/go/v7/arrow/memory"
9
+
10
10
"github.com/influxdata/flux/codes"
11
11
"github.com/influxdata/flux/internal/errors"
12
12
"github.com/influxdata/flux/memory"
@@ -103,10 +103,23 @@ type Builder interface {
103
103
NewArray () Array
104
104
}
105
105
106
+ type binaryArray interface {
107
+ NullN () int
108
+ NullBitmapBytes () []byte
109
+ IsNull (i int ) bool
110
+ IsValid (i int ) bool
111
+ Data () arrow.ArrayData
112
+ Len () int
113
+ ValueBytes () []byte
114
+ ValueLen (i int ) int
115
+ ValueOffset (i int ) int
116
+ ValueString (i int ) string
117
+ Retain ()
118
+ Release ()
119
+ }
120
+
106
121
type String struct {
107
- length int
108
- data * array.Binary
109
- value * stringValue
122
+ binaryArray
110
123
}
111
124
112
125
// NewStringFromBinaryArray creates an instance of String from
@@ -118,140 +131,90 @@ type String struct {
118
131
func NewStringFromBinaryArray (data * array.Binary ) * String {
119
132
data .Retain ()
120
133
return & String {
121
- data : data ,
134
+ binaryArray : data ,
122
135
}
123
136
}
124
137
125
138
func (a * String ) DataType () DataType {
126
139
return StringType
127
140
}
128
- func (a * String ) NullN () int {
129
- if a .data != nil {
130
- return a .data .NullN ()
131
- }
132
- return 0
133
- }
134
- func (a * String ) NullBitmapBytes () []byte {
135
- if a .data != nil {
136
- return a .data .NullBitmapBytes ()
137
- }
138
- return nil
139
- }
140
- func (a * String ) IsNull (i int ) bool {
141
- if a .data != nil {
142
- return a .data .IsNull (i )
143
- }
144
- return false
145
- }
146
- func (a * String ) IsValid (i int ) bool {
147
- if a .data != nil {
148
- return a .data .IsValid (i )
149
- }
150
- return true
151
- }
152
- func (a * String ) Data () arrow.ArrayData {
153
- if a .data != nil {
154
- return a .data .Data ()
155
- }
156
- return nil
157
- }
158
- func (a * String ) Len () int {
159
- if a .data != nil {
160
- return a .data .Len ()
161
- }
162
- return a .length
163
- }
164
- func (a * String ) Retain () {
165
- if a .data != nil {
166
- a .data .Retain ()
167
- return
168
- }
169
- a .value .Retain ()
170
- }
171
- func (a * String ) Release () {
172
- if a .data != nil {
173
- a .data .Release ()
174
- return
175
- }
176
- a .value .Release ()
177
- }
141
+
178
142
func (a * String ) Slice (i , j int ) Array {
179
- if a .data != nil {
180
- data := array .NewSliceData (a .data .Data (), int64 (i ), int64 (j ))
181
- defer data .Release ()
182
- return & String {
183
- data : array .NewBinaryData (data ),
184
- }
143
+ slice , ok := a .binaryArray .(interface { Slice (i , j int ) binaryArray })
144
+ if ok {
145
+ return & String {binaryArray : slice .Slice (i , j )}
185
146
}
186
- a .value .Retain ()
147
+ data := array .NewSliceData (a .binaryArray .Data (), int64 (i ), int64 (j ))
148
+ defer data .Release ()
187
149
return & String {
188
- value : a .value ,
189
- length : j - i ,
150
+ binaryArray : array .NewBinaryData (data ),
190
151
}
191
152
}
192
153
193
- // ValueBytes returns a byte slice containing the value of this string
194
- // at index i. This slice points to the contents of the data buffer and
195
- // is only valid for the lifetime of the array.
196
- func (a * String ) ValueBytes (i int ) []byte {
197
- if a .data != nil {
198
- return a .data .Value (i )
199
- }
200
- return a .value .Bytes ()
201
- }
202
-
203
- // Value returns a string copy of the value stored at index i. The
204
- // returned value will outlive the array and is safe to use like any
205
- // other go string. The memory backing the string will be allocated by
206
- // the runtime, rather than any provided allocator.
154
+ // Value returns a string view of the bytes in the array. The string
155
+ // is only valid for the lifetime of the array. Care should be taken not
156
+ // to store this string without also retaining the array.
207
157
func (a * String ) Value (i int ) string {
208
- return string ( a . ValueBytes ( i ) )
158
+ return a . ValueString ( i )
209
159
}
210
- func (a * String ) ValueLen (i int ) int {
211
- if a .data != nil {
212
- return a .data .ValueLen (i )
160
+
161
+ // ValueRef returns a reference to the memory buffer and location that
162
+ // stores the value at i. The reference is only valid for as long as the
163
+ // array is, the buffer needs to be retained if further access is
164
+ // required.
165
+ func (a * String ) ValueRef (i int ) StringRef {
166
+ if vr , ok := a .binaryArray .(interface { ValueRef (int ) StringRef }); ok {
167
+ return vr .ValueRef (i )
168
+ }
169
+ return StringRef {
170
+ buf : a .Data ().Buffers ()[2 ],
171
+ off : a .ValueOffset (i ),
172
+ len : a .ValueLen (i ),
213
173
}
214
- return a .value .Len ()
215
174
}
216
- func (a * String ) IsConstant () bool {
217
- return a .data == nil
175
+
176
+ // ValueCopy returns the value at the requested position copied into a
177
+ // new memory location. This value will remain valid after the array is
178
+ // released, but is not tracked by the memory allocator.
179
+ //
180
+ // This function is intended to be temporary while changes are being
181
+ // made to reduce the amount of unaccounted data memory.
182
+ func (a * String ) ValueCopy (i int ) string {
183
+ return string (a .ValueRef (i ).Bytes ())
218
184
}
219
185
220
- type stringValue struct {
221
- rc int64
222
- data []byte
186
+ func (a * String ) IsConstant () bool {
187
+ ic , ok := a .binaryArray .(interface { IsConstant () bool })
188
+ return ok && ic .IsConstant ()
189
+ }
223
190
224
- mem arrowmem.Allocator
191
+ // StringRef contains a referenct to the storage for a value.
192
+ type StringRef struct {
193
+ buf * arrowmem.Buffer
194
+ off int
195
+ len int
225
196
}
226
197
227
- func (v * stringValue ) Retain () {
228
- if v == nil {
229
- return
230
- }
231
- atomic .AddInt64 (& v .rc , 1 )
198
+ // Buffer returns the memory buffer that contains the value.
199
+ func (r StringRef ) Buffer () * arrowmem.Buffer {
200
+ return r .buf
232
201
}
233
202
234
- func (v * stringValue ) Release () {
235
- if v == nil {
236
- return
237
- }
238
- if atomic .AddInt64 (& v .rc , - 1 ) == 0 {
239
- v .mem .Free (v .data )
240
- }
203
+ // Offset returns the offset into the memory buffer at which the value
204
+ // starts.
205
+ func (r StringRef ) Offset () int {
206
+ return r .off
241
207
}
242
208
243
- func (v * stringValue ) Bytes () []byte {
244
- if v == nil {
245
- return nil
246
- }
247
- return v .data
209
+ // Len returns the length of the value.
210
+ func (r StringRef ) Len () int {
211
+ return r .len
248
212
}
249
213
250
- func (v * stringValue ) Len () int {
251
- if v == nil {
252
- return 0
253
- }
254
- return len (v .data )
214
+ // Bytes returns the bytes from the memory buffer that contain the
215
+ // value.
216
+ func (r StringRef ) Bytes () []byte {
217
+ return r .buf .Bytes ()[r .off : r .off + r .len ]
255
218
}
256
219
257
220
type sliceable interface {
0 commit comments