]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/go/arrow/datatype_nested.go
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / go / arrow / datatype_nested.go
CommitLineData
1d09f67e
TL
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
17package arrow
18
19import (
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.
26type ListType struct {
27 elem Field
28}
29
30func 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
41func 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.
50func 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
57func (*ListType) ID() Type { return LIST }
58func (*ListType) Name() string { return "list" }
59
60func (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
67func (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
75func (t *ListType) SetElemMetadata(md Metadata) { t.elem.Metadata = md }
76
77func (t *ListType) SetElemNullable(n bool) { t.elem.Nullable = n }
78
79// Elem returns the ListType's element type.
80func (t *ListType) Elem() DataType { return t.elem.Type }
81
82func (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.
88type FixedSizeListType struct {
89 n int32 // number of elements in the list
90 elem Field
91}
92
93func 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
109func 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.
121func 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
131func (*FixedSizeListType) ID() Type { return FIXED_SIZE_LIST }
132func (*FixedSizeListType) Name() string { return "fixed_size_list" }
133func (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.
141func (t *FixedSizeListType) Elem() DataType { return t.elem.Type }
142
143// Len returns the FixedSizeListType's size.
144func (t *FixedSizeListType) Len() int32 { return t.n }
145
146func (t *FixedSizeListType) ElemField() Field {
147 return t.elem
148}
149
150func (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.
160type 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.
170func 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
199func (*StructType) ID() Type { return STRUCT }
200func (*StructType) Name() string { return "struct" }
201
202func (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
215func (t *StructType) Fields() []Field { return t.fields }
216func (t *StructType) Field(i int) Field { return t.fields[i] }
217
218func (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
226func (t *StructType) FieldIdx(name string) (int, bool) {
227 i, ok := t.index[name]
228 return i, ok
229}
230
231func (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
247type MapType struct {
248 value *ListType
249 KeysSorted bool
250}
251
252func 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
260func (*MapType) ID() Type { return MAP }
261func (*MapType) Name() string { return "map" }
262
263func (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
275func (t *MapType) KeyField() Field { return t.value.Elem().(*StructType).Field(0) }
276func (t *MapType) KeyType() DataType { return t.KeyField().Type }
277func (t *MapType) ItemField() Field { return t.value.Elem().(*StructType).Field(1) }
278func (t *MapType) ItemType() DataType { return t.ItemField().Type }
279func (t *MapType) ValueType() *StructType { return t.value.Elem().(*StructType) }
280func (t *MapType) ValueField() Field {
281 return Field{
282 Name: "entries",
283 Type: t.ValueType(),
284 }
285}
286
287func (t *MapType) SetItemNullable(nullable bool) {
288 t.value.Elem().(*StructType).fields[1].Nullable = nullable
289}
290
291func (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
305type 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
312func (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
332func (f Field) HasMetadata() bool { return f.Metadata.Len() != 0 }
333
334func (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
348func (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
361var (
362 _ DataType = (*ListType)(nil)
363 _ DataType = (*StructType)(nil)
364 _ DataType = (*MapType)(nil)
365)