]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/go/arrow/datatype_nested.go
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / go / arrow / datatype_nested.go
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 package arrow
18
19 import (
20 "fmt"
21 "strings"
22 )
23
24 // ListType describes a nested type in which each array slot contains
25 // a variable-size sequence of values, all having the same relative type.
26 type ListType struct {
27 elem Field
28 }
29
30 func ListOfField(f Field) *ListType {
31 if f.Type == nil {
32 panic("arrow: nil type for list field")
33 }
34 return &ListType{elem: f}
35 }
36
37 // ListOf returns the list type with element type t.
38 // For example, if t represents int32, ListOf(t) represents []int32.
39 //
40 // ListOf panics if t is nil or invalid. NullableElem defaults to true
41 func ListOf(t DataType) *ListType {
42 if t == nil {
43 panic("arrow: nil DataType")
44 }
45 return &ListType{elem: Field{Name: "item", Type: t, Nullable: true}}
46 }
47
48 // ListOfNonNullable is like ListOf but NullableElem defaults to false, indicating
49 // that the child type should be marked as non-nullable.
50 func ListOfNonNullable(t DataType) *ListType {
51 if t == nil {
52 panic("arrow: nil DataType")
53 }
54 return &ListType{elem: Field{Name: "item", Type: t, Nullable: false}}
55 }
56
57 func (*ListType) ID() Type { return LIST }
58 func (*ListType) Name() string { return "list" }
59
60 func (t *ListType) String() string {
61 if t.elem.Nullable {
62 return fmt.Sprintf("list<%s: %s, nullable>", t.elem.Name, t.elem.Type)
63 }
64 return fmt.Sprintf("list<%s: %s>", t.elem.Name, t.elem.Type)
65 }
66
67 func (t *ListType) Fingerprint() string {
68 child := t.elem.Type.Fingerprint()
69 if len(child) > 0 {
70 return typeFingerprint(t) + "{" + child + "}"
71 }
72 return ""
73 }
74
75 func (t *ListType) SetElemMetadata(md Metadata) { t.elem.Metadata = md }
76
77 func (t *ListType) SetElemNullable(n bool) { t.elem.Nullable = n }
78
79 // Elem returns the ListType's element type.
80 func (t *ListType) Elem() DataType { return t.elem.Type }
81
82 func (t *ListType) ElemField() Field {
83 return t.elem
84 }
85
86 // FixedSizeListType describes a nested type in which each array slot contains
87 // a fixed-size sequence of values, all having the same relative type.
88 type FixedSizeListType struct {
89 n int32 // number of elements in the list
90 elem Field
91 }
92
93 func FixedSizeListOfField(n int32, f Field) *FixedSizeListType {
94 if f.Type == nil {
95 panic("arrow: nil DataType")
96 }
97 if n <= 0 {
98 panic("arrow: invalid size")
99 }
100 return &FixedSizeListType{n: n, elem: f}
101 }
102
103 // FixedSizeListOf returns the list type with element type t.
104 // For example, if t represents int32, FixedSizeListOf(10, t) represents [10]int32.
105 //
106 // FixedSizeListOf panics if t is nil or invalid.
107 // FixedSizeListOf panics if n is <= 0.
108 // NullableElem defaults to true
109 func FixedSizeListOf(n int32, t DataType) *FixedSizeListType {
110 if t == nil {
111 panic("arrow: nil DataType")
112 }
113 if n <= 0 {
114 panic("arrow: invalid size")
115 }
116 return &FixedSizeListType{n: n, elem: Field{Name: "item", Type: t, Nullable: true}}
117 }
118
119 // FixedSizeListOfNonNullable is like FixedSizeListOf but NullableElem defaults to false
120 // indicating that the child type should be marked as non-nullable.
121 func FixedSizeListOfNonNullable(n int32, t DataType) *FixedSizeListType {
122 if t == nil {
123 panic("arrow: nil DataType")
124 }
125 if n <= 0 {
126 panic("arrow: invalid size")
127 }
128 return &FixedSizeListType{n: n, elem: Field{Name: "item", Type: t, Nullable: false}}
129 }
130
131 func (*FixedSizeListType) ID() Type { return FIXED_SIZE_LIST }
132 func (*FixedSizeListType) Name() string { return "fixed_size_list" }
133 func (t *FixedSizeListType) String() string {
134 if t.elem.Nullable {
135 return fmt.Sprintf("fixed_size_list<%s: %s, nullable>[%d]", t.elem.Name, t.elem.Type, t.n)
136 }
137 return fmt.Sprintf("fixed_size_list<%s: %s>[%d]", t.elem.Name, t.elem.Type, t.n)
138 }
139
140 // Elem returns the FixedSizeListType's element type.
141 func (t *FixedSizeListType) Elem() DataType { return t.elem.Type }
142
143 // Len returns the FixedSizeListType's size.
144 func (t *FixedSizeListType) Len() int32 { return t.n }
145
146 func (t *FixedSizeListType) ElemField() Field {
147 return t.elem
148 }
149
150 func (t *FixedSizeListType) Fingerprint() string {
151 child := t.elem.Type.Fingerprint()
152 if len(child) > 0 {
153 return fmt.Sprintf("%s[%d]{%s}", typeFingerprint(t), t.n, child)
154 }
155 return ""
156 }
157
158 // StructType describes a nested type parameterized by an ordered sequence
159 // of relative types, called its fields.
160 type StructType struct {
161 fields []Field
162 index map[string]int
163 meta Metadata
164 }
165
166 // StructOf returns the struct type with fields fs.
167 //
168 // StructOf panics if there are duplicated fields.
169 // StructOf panics if there is a field with an invalid DataType.
170 func StructOf(fs ...Field) *StructType {
171 n := len(fs)
172 if n == 0 {
173 return &StructType{}
174 }
175
176 t := &StructType{
177 fields: make([]Field, n),
178 index: make(map[string]int, n),
179 }
180 for i, f := range fs {
181 if f.Type == nil {
182 panic("arrow: field with nil DataType")
183 }
184 t.fields[i] = Field{
185 Name: f.Name,
186 Type: f.Type,
187 Nullable: f.Nullable,
188 Metadata: f.Metadata.clone(),
189 }
190 if _, dup := t.index[f.Name]; dup {
191 panic(fmt.Errorf("arrow: duplicate field with name %q", f.Name))
192 }
193 t.index[f.Name] = i
194 }
195
196 return t
197 }
198
199 func (*StructType) ID() Type { return STRUCT }
200 func (*StructType) Name() string { return "struct" }
201
202 func (t *StructType) String() string {
203 o := new(strings.Builder)
204 o.WriteString("struct<")
205 for i, f := range t.fields {
206 if i > 0 {
207 o.WriteString(", ")
208 }
209 o.WriteString(fmt.Sprintf("%s: %v", f.Name, f.Type))
210 }
211 o.WriteString(">")
212 return o.String()
213 }
214
215 func (t *StructType) Fields() []Field { return t.fields }
216 func (t *StructType) Field(i int) Field { return t.fields[i] }
217
218 func (t *StructType) FieldByName(name string) (Field, bool) {
219 i, ok := t.index[name]
220 if !ok {
221 return Field{}, false
222 }
223 return t.fields[i], true
224 }
225
226 func (t *StructType) FieldIdx(name string) (int, bool) {
227 i, ok := t.index[name]
228 return i, ok
229 }
230
231 func (t *StructType) Fingerprint() string {
232 var b strings.Builder
233 b.WriteString(typeFingerprint(t))
234 b.WriteByte('{')
235 for _, c := range t.fields {
236 child := c.Fingerprint()
237 if len(child) == 0 {
238 return ""
239 }
240 b.WriteString(child)
241 b.WriteByte(';')
242 }
243 b.WriteByte('}')
244 return b.String()
245 }
246
247 type MapType struct {
248 value *ListType
249 KeysSorted bool
250 }
251
252 func MapOf(key, item DataType) *MapType {
253 if key == nil || item == nil {
254 panic("arrow: nil key or item type for MapType")
255 }
256
257 return &MapType{value: ListOf(StructOf(Field{Name: "key", Type: key}, Field{Name: "value", Type: item, Nullable: true}))}
258 }
259
260 func (*MapType) ID() Type { return MAP }
261 func (*MapType) Name() string { return "map" }
262
263 func (t *MapType) String() string {
264 var o strings.Builder
265 o.WriteString(fmt.Sprintf("map<%s, %s",
266 t.value.Elem().(*StructType).Field(0).Type,
267 t.value.Elem().(*StructType).Field(1).Type))
268 if t.KeysSorted {
269 o.WriteString(", keys_sorted")
270 }
271 o.WriteString(">")
272 return o.String()
273 }
274
275 func (t *MapType) KeyField() Field { return t.value.Elem().(*StructType).Field(0) }
276 func (t *MapType) KeyType() DataType { return t.KeyField().Type }
277 func (t *MapType) ItemField() Field { return t.value.Elem().(*StructType).Field(1) }
278 func (t *MapType) ItemType() DataType { return t.ItemField().Type }
279 func (t *MapType) ValueType() *StructType { return t.value.Elem().(*StructType) }
280 func (t *MapType) ValueField() Field {
281 return Field{
282 Name: "entries",
283 Type: t.ValueType(),
284 }
285 }
286
287 func (t *MapType) SetItemNullable(nullable bool) {
288 t.value.Elem().(*StructType).fields[1].Nullable = nullable
289 }
290
291 func (t *MapType) Fingerprint() string {
292 keyFingerprint := t.KeyType().Fingerprint()
293 itemFingerprint := t.ItemType().Fingerprint()
294 if keyFingerprint == "" || itemFingerprint == "" {
295 return ""
296 }
297
298 fingerprint := typeFingerprint(t)
299 if t.KeysSorted {
300 fingerprint += "s"
301 }
302 return fingerprint + "{" + keyFingerprint + itemFingerprint + "}"
303 }
304
305 type Field struct {
306 Name string // Field name
307 Type DataType // The field's data type
308 Nullable bool // Fields can be nullable
309 Metadata Metadata // The field's metadata, if any
310 }
311
312 func (f Field) Fingerprint() string {
313 typeFingerprint := f.Type.Fingerprint()
314 if typeFingerprint == "" {
315 return ""
316 }
317
318 var b strings.Builder
319 b.WriteByte('F')
320 if f.Nullable {
321 b.WriteByte('n')
322 } else {
323 b.WriteByte('N')
324 }
325 b.WriteString(f.Name)
326 b.WriteByte('{')
327 b.WriteString(typeFingerprint)
328 b.WriteByte('}')
329 return b.String()
330 }
331
332 func (f Field) HasMetadata() bool { return f.Metadata.Len() != 0 }
333
334 func (f Field) Equal(o Field) bool {
335 switch {
336 case f.Name != o.Name:
337 return false
338 case f.Nullable != o.Nullable:
339 return false
340 case !TypeEqual(f.Type, o.Type, CheckMetadata()):
341 return false
342 case !f.Metadata.Equal(o.Metadata):
343 return false
344 }
345 return true
346 }
347
348 func (f Field) String() string {
349 o := new(strings.Builder)
350 nullable := ""
351 if f.Nullable {
352 nullable = ", nullable"
353 }
354 fmt.Fprintf(o, "%s: type=%v%v", f.Name, f.Type, nullable)
355 if f.HasMetadata() {
356 fmt.Fprintf(o, "\n%*.smetadata: %v", len(f.Name)+2, "", f.Metadata)
357 }
358 return o.String()
359 }
360
361 var (
362 _ DataType = (*ListType)(nil)
363 _ DataType = (*StructType)(nil)
364 _ DataType = (*MapType)(nil)
365 )