1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package schema
18
19 import (
20 "testing"
21
22 "github.com/apache/arrow/go/v15/parquet"
23 format "github.com/apache/arrow/go/v15/parquet/internal/gen-go/parquet"
24 "github.com/stretchr/testify/assert"
25 "github.com/stretchr/testify/suite"
26 )
27
28 type schemaElementConstruction struct {
29 node Node
30 element *format.SchemaElement
31 name string
32 expectConverted bool
33 converted ConvertedType
34 expectLogical bool
35 checkLogical func(*format.SchemaElement) bool
36 }
37
38 type decimalSchemaElementConstruction struct {
39 schemaElementConstruction
40 precision int
41 scale int
42 }
43
44 type temporalSchemaElementConstruction struct {
45 schemaElementConstruction
46 adjusted bool
47 unit TimeUnitType
48 getUnit func(*format.SchemaElement) *format.TimeUnit
49 }
50
51 type intSchemaElementConstruction struct {
52 schemaElementConstruction
53 width int8
54 signed bool
55 }
56
57 type legacySchemaElementConstructArgs struct {
58 name string
59 physical parquet.Type
60 len int
61 expectConverted bool
62 converted ConvertedType
63 expectLogical bool
64 checkLogical func(*format.SchemaElement) bool
65 }
66
67 type schemaElementConstructArgs struct {
68 name string
69 logical LogicalType
70 physical parquet.Type
71 len int
72 expectConverted bool
73 converted ConvertedType
74 expectLogical bool
75 checkLogical func(*format.SchemaElement) bool
76 }
77 type SchemaElementConstructionSuite struct {
78 suite.Suite
79 }
80
81 func (s *SchemaElementConstructionSuite) reconstruct(c schemaElementConstructArgs) *schemaElementConstruction {
82 ret := &schemaElementConstruction{
83 node: MustPrimitive(NewPrimitiveNodeLogical(c.name, parquet.Repetitions.Required, c.logical, c.physical, c.len, -1)),
84 name: c.name,
85 expectConverted: c.expectConverted,
86 converted: c.converted,
87 expectLogical: c.expectLogical,
88 checkLogical: c.checkLogical,
89 }
90 ret.element = ret.node.toThrift()
91 return ret
92 }
93
94 func (s *SchemaElementConstructionSuite) legacyReconstruct(c legacySchemaElementConstructArgs) *schemaElementConstruction {
95 ret := &schemaElementConstruction{
96 node: MustPrimitive(NewPrimitiveNodeConverted(c.name, parquet.Repetitions.Required, c.physical, c.converted, c.len, 0, 0, -1)),
97 name: c.name,
98 expectConverted: c.expectConverted,
99 converted: c.converted,
100 expectLogical: c.expectLogical,
101 checkLogical: c.checkLogical,
102 }
103 ret.element = ret.node.toThrift()
104 return ret
105 }
106
107 func (s *SchemaElementConstructionSuite) inspect(c *schemaElementConstruction) {
108 if c.expectConverted {
109 s.True(c.element.IsSetConvertedType())
110 s.Equal(c.converted, ConvertedType(*c.element.ConvertedType))
111 } else {
112 s.False(c.element.IsSetConvertedType())
113 }
114 if c.expectLogical {
115 s.True(c.element.IsSetLogicalType())
116 s.True(c.checkLogical(c.element))
117 } else {
118 s.False(c.element.IsSetLogicalType())
119 }
120 }
121
122 func (s *SchemaElementConstructionSuite) TestSimple() {
123 checkNone := func(*format.SchemaElement) bool { return true }
124
125 tests := []struct {
126 name string
127 args *schemaElementConstructArgs
128 legacy *legacySchemaElementConstructArgs
129 }{
130 {"string", &schemaElementConstructArgs{
131 "string", StringLogicalType{}, parquet.Types.ByteArray, -1, true, ConvertedTypes.UTF8, true,
132 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetSTRING() },
133 }, nil},
134 {"enum", &schemaElementConstructArgs{
135 "enum", EnumLogicalType{}, parquet.Types.ByteArray, -1, true, ConvertedTypes.Enum, true,
136 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetENUM() },
137 }, nil},
138 {"date", &schemaElementConstructArgs{
139 "date", DateLogicalType{}, parquet.Types.Int32, -1, true, ConvertedTypes.Date, true,
140 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetDATE() },
141 }, nil},
142 {"interval", &schemaElementConstructArgs{
143 "interval", IntervalLogicalType{}, parquet.Types.FixedLenByteArray, 12, true, ConvertedTypes.Interval, false,
144 checkNone,
145 }, nil},
146 {"null", &schemaElementConstructArgs{
147 "null", NullLogicalType{}, parquet.Types.Double, -1, false, ConvertedTypes.NA, true,
148 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetUNKNOWN() },
149 }, nil},
150 {"json", &schemaElementConstructArgs{
151 "json", JSONLogicalType{}, parquet.Types.ByteArray, -1, true, ConvertedTypes.JSON, true,
152 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetJSON() },
153 }, nil},
154 {"bson", &schemaElementConstructArgs{
155 "bson", BSONLogicalType{}, parquet.Types.ByteArray, -1, true, ConvertedTypes.BSON, true,
156 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetBSON() },
157 }, nil},
158 {"uuid", &schemaElementConstructArgs{
159 "uuid", UUIDLogicalType{}, parquet.Types.FixedLenByteArray, 16, false, ConvertedTypes.NA, true,
160 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetUUID() },
161 }, nil},
162 {"float16", &schemaElementConstructArgs{
163 "float16", Float16LogicalType{}, parquet.Types.FixedLenByteArray, 2, false, ConvertedTypes.NA, true,
164 func(e *format.SchemaElement) bool { return e.LogicalType.IsSetFLOAT16() },
165 }, nil},
166 {"none", &schemaElementConstructArgs{
167 "none", NoLogicalType{}, parquet.Types.Int64, -1, false, ConvertedTypes.NA, false,
168 checkNone,
169 }, nil},
170 {"unknown", &schemaElementConstructArgs{
171 "unknown", UnknownLogicalType{}, parquet.Types.Int64, -1, true, ConvertedTypes.NA, false,
172 checkNone,
173 }, nil},
174 {"timestamp_ms", nil, &legacySchemaElementConstructArgs{
175 "timestamp_ms", parquet.Types.Int64, -1, true, ConvertedTypes.TimestampMillis, false, checkNone}},
176 {"timestamp_us", nil, &legacySchemaElementConstructArgs{
177 "timestamp_us", parquet.Types.Int64, -1, true, ConvertedTypes.TimestampMicros, false, checkNone}},
178 }
179 for _, tt := range tests {
180 s.Run(tt.name, func() {
181 var sc *schemaElementConstruction
182 if tt.args != nil {
183 sc = s.reconstruct(*tt.args)
184 } else {
185 sc = s.legacyReconstruct(*tt.legacy)
186 }
187 s.Equal(tt.name, sc.element.Name)
188 s.inspect(sc)
189 })
190 }
191 }
192
193 func (s *SchemaElementConstructionSuite) reconstructDecimal(c schemaElementConstructArgs) *decimalSchemaElementConstruction {
194 ret := s.reconstruct(c)
195 dec := c.logical.(*DecimalLogicalType)
196 return &decimalSchemaElementConstruction{*ret, int(dec.Precision()), int(dec.Scale())}
197 }
198
199 func (s *SchemaElementConstructionSuite) inspectDecimal(d *decimalSchemaElementConstruction) {
200 s.inspect(&d.schemaElementConstruction)
201 s.EqualValues(d.precision, d.element.GetPrecision())
202 s.EqualValues(d.scale, d.element.GetScale())
203 s.EqualValues(d.precision, d.element.LogicalType.DECIMAL.Precision)
204 s.EqualValues(d.scale, d.element.LogicalType.DECIMAL.Scale)
205 }
206
207 func (s *SchemaElementConstructionSuite) TestDecimal() {
208 checkDecimal := func(p *format.SchemaElement) bool { return p.LogicalType.IsSetDECIMAL() }
209
210 tests := []schemaElementConstructArgs{
211 {
212 name: "decimal16_6", logical: NewDecimalLogicalType(16 , 6 ),
213 physical: parquet.Types.Int64, len: -1, expectConverted: true, converted: ConvertedTypes.Decimal,
214 expectLogical: true, checkLogical: checkDecimal,
215 },
216 {
217 name: "decimal1_0", logical: NewDecimalLogicalType(1 , 0 ),
218 physical: parquet.Types.Int32, len: -1, expectConverted: true, converted: ConvertedTypes.Decimal,
219 expectLogical: true, checkLogical: checkDecimal,
220 },
221 {
222 name: "decimal10", logical: NewDecimalLogicalType(10 , 0 ),
223 physical: parquet.Types.Int64, len: -1, expectConverted: true, converted: ConvertedTypes.Decimal,
224 expectLogical: true, checkLogical: checkDecimal,
225 },
226 {
227 name: "decimal11_11", logical: NewDecimalLogicalType(11 , 11 ),
228 physical: parquet.Types.Int64, len: -1, expectConverted: true, converted: ConvertedTypes.Decimal,
229 expectLogical: true, checkLogical: checkDecimal,
230 },
231 }
232 for _, tt := range tests {
233 s.Run(tt.name, func() {
234 d := s.reconstructDecimal(tt)
235 s.Equal(tt.name, d.element.Name)
236 s.inspectDecimal(d)
237 })
238 }
239 }
240
241 func (s *SchemaElementConstructionSuite) reconstructTemporal(c schemaElementConstructArgs, getUnit func(*format.SchemaElement) *format.TimeUnit) *temporalSchemaElementConstruction {
242 base := s.reconstruct(c)
243 t := c.logical.(TemporalLogicalType)
244 return &temporalSchemaElementConstruction{
245 *base,
246 t.IsAdjustedToUTC(),
247 t.TimeUnit(),
248 getUnit,
249 }
250 }
251
252 func (s *SchemaElementConstructionSuite) inspectTemporal(t *temporalSchemaElementConstruction) {
253 s.inspect(&t.schemaElementConstruction)
254 switch t.unit {
255 case TimeUnitMillis:
256 s.True(t.getUnit(t.element).IsSetMILLIS())
257 case TimeUnitMicros:
258 s.True(t.getUnit(t.element).IsSetMICROS())
259 case TimeUnitNanos:
260 s.True(t.getUnit(t.element).IsSetNANOS())
261 case TimeUnitUnknown:
262 fallthrough
263 default:
264 s.Fail("invalid time unit in test case")
265 }
266 }
267
268 func (s *SchemaElementConstructionSuite) TestTemporal() {
269 checkTime := func(p *format.SchemaElement) bool {
270 return p.LogicalType.IsSetTIME()
271 }
272 checkTimestamp := func(p *format.SchemaElement) bool {
273 return p.LogicalType.IsSetTIMESTAMP()
274 }
275
276 getTimeUnit := func(p *format.SchemaElement) *format.TimeUnit {
277 return p.LogicalType.TIME.Unit
278 }
279 getTimestampUnit := func(p *format.SchemaElement) *format.TimeUnit {
280 return p.LogicalType.TIMESTAMP.Unit
281 }
282
283 timeTests := []schemaElementConstructArgs{
284 {
285 name: "time_T_ms", logical: NewTimeLogicalType(true, TimeUnitMillis), physical: parquet.Types.Int32, len: -1,
286 expectConverted: true, converted: ConvertedTypes.TimeMillis, expectLogical: true, checkLogical: checkTime,
287 },
288 {
289 name: "time_F_ms", logical: NewTimeLogicalType(false, TimeUnitMillis), physical: parquet.Types.Int32, len: -1,
290 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTime,
291 },
292 {
293 name: "time_T_us", logical: NewTimeLogicalType(true, TimeUnitMicros), physical: parquet.Types.Int64, len: -1,
294 expectConverted: true, converted: ConvertedTypes.TimeMicros, expectLogical: true, checkLogical: checkTime,
295 },
296 {
297 name: "time_F_us", logical: NewTimeLogicalType(false, TimeUnitMicros), physical: parquet.Types.Int64, len: -1,
298 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTime,
299 },
300 {
301 name: "time_T_ns", logical: NewTimeLogicalType(true, TimeUnitNanos), physical: parquet.Types.Int64, len: -1,
302 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTime,
303 },
304 {
305 name: "time_F_ns", logical: NewTimeLogicalType(false, TimeUnitNanos), physical: parquet.Types.Int64, len: -1,
306 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTime,
307 },
308 }
309 timeStampTests := []schemaElementConstructArgs{
310 {
311 name: "timestamp_T_ms", logical: NewTimestampLogicalType(true, TimeUnitMillis), physical: parquet.Types.Int64, len: -1,
312 expectConverted: true, converted: ConvertedTypes.TimestampMillis, expectLogical: true, checkLogical: checkTimestamp,
313 },
314 {
315 name: "timestamp_F_ms", logical: NewTimestampLogicalType(false, TimeUnitMillis), physical: parquet.Types.Int64, len: -1,
316 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTimestamp,
317 },
318 {
319 name: "timestamp_F_ms_force", logical: NewTimestampLogicalTypeForce(false, TimeUnitMillis), physical: parquet.Types.Int64, len: -1,
320 expectConverted: true, converted: ConvertedTypes.TimestampMillis, expectLogical: true, checkLogical: checkTimestamp,
321 },
322 {
323 name: "timestamp_T_us", logical: NewTimestampLogicalType(true, TimeUnitMicros), physical: parquet.Types.Int64, len: -1,
324 expectConverted: true, converted: ConvertedTypes.TimestampMicros, expectLogical: true, checkLogical: checkTimestamp,
325 },
326 {
327 name: "timestamp_F_us", logical: NewTimestampLogicalType(false, TimeUnitMicros), physical: parquet.Types.Int64, len: -1,
328 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTimestamp,
329 },
330 {
331 name: "timestamp_F_us_force", logical: NewTimestampLogicalTypeForce(false, TimeUnitMicros), physical: parquet.Types.Int64, len: -1,
332 expectConverted: true, converted: ConvertedTypes.TimestampMicros, expectLogical: true, checkLogical: checkTimestamp,
333 },
334 {
335 name: "timestamp_T_ns", logical: NewTimestampLogicalType(true, TimeUnitNanos), physical: parquet.Types.Int64, len: -1,
336 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTimestamp,
337 },
338 {
339 name: "timestamp_F_ns", logical: NewTimestampLogicalType(false, TimeUnitNanos), physical: parquet.Types.Int64, len: -1,
340 expectConverted: false, converted: ConvertedTypes.NA, expectLogical: true, checkLogical: checkTimestamp,
341 },
342 }
343
344 for _, tt := range timeTests {
345 s.Run(tt.name, func() {
346 t := s.reconstructTemporal(tt, getTimeUnit)
347 s.Equal(t.adjusted, t.element.LogicalType.TIME.IsAdjustedToUTC)
348 s.inspectTemporal(t)
349 })
350 }
351 for _, tt := range timeStampTests {
352 s.Run(tt.name, func() {
353 t := s.reconstructTemporal(tt, getTimestampUnit)
354 s.Equal(t.adjusted, t.element.LogicalType.TIMESTAMP.IsAdjustedToUTC)
355 s.inspectTemporal(t)
356 })
357 }
358 }
359
360 func (s *SchemaElementConstructionSuite) reconstructInteger(c schemaElementConstructArgs) *intSchemaElementConstruction {
361 base := s.reconstruct(c)
362 l := c.logical.(*IntLogicalType)
363 return &intSchemaElementConstruction{
364 *base,
365 l.BitWidth(),
366 l.IsSigned(),
367 }
368 }
369
370 func (s *SchemaElementConstructionSuite) inspectInt(i *intSchemaElementConstruction) {
371 s.inspect(&i.schemaElementConstruction)
372 s.Equal(i.width, i.element.LogicalType.INTEGER.BitWidth)
373 s.Equal(i.signed, i.element.LogicalType.INTEGER.IsSigned)
374 }
375
376 func (s *SchemaElementConstructionSuite) TestIntegerCases() {
377 checkInt := func(p *format.SchemaElement) bool { return p.LogicalType.IsSetINTEGER() }
378
379 tests := []schemaElementConstructArgs{
380 {
381 name: "uint8", logical: NewIntLogicalType(8, false), physical: parquet.Types.Int32, len: -1,
382 expectConverted: true, converted: ConvertedTypes.Uint8, expectLogical: true, checkLogical: checkInt,
383 },
384 {
385 name: "uint16", logical: NewIntLogicalType(16, false), physical: parquet.Types.Int32, len: -1,
386 expectConverted: true, converted: ConvertedTypes.Uint16, expectLogical: true, checkLogical: checkInt,
387 },
388 {
389 name: "uint32", logical: NewIntLogicalType(32, false), physical: parquet.Types.Int32, len: -1,
390 expectConverted: true, converted: ConvertedTypes.Uint32, expectLogical: true, checkLogical: checkInt,
391 },
392 {
393 name: "uint64", logical: NewIntLogicalType(64, false), physical: parquet.Types.Int64, len: -1,
394 expectConverted: true, converted: ConvertedTypes.Uint64, expectLogical: true, checkLogical: checkInt,
395 },
396 {
397 name: "int8", logical: NewIntLogicalType(8, true), physical: parquet.Types.Int32, len: -1,
398 expectConverted: true, converted: ConvertedTypes.Int8, expectLogical: true, checkLogical: checkInt,
399 },
400 {
401 name: "int16", logical: NewIntLogicalType(16, true), physical: parquet.Types.Int32, len: -1,
402 expectConverted: true, converted: ConvertedTypes.Int16, expectLogical: true, checkLogical: checkInt,
403 },
404 {
405 name: "int32", logical: NewIntLogicalType(32, true), physical: parquet.Types.Int32, len: -1,
406 expectConverted: true, converted: ConvertedTypes.Int32, expectLogical: true, checkLogical: checkInt,
407 },
408 {
409 name: "int64", logical: NewIntLogicalType(64, true), physical: parquet.Types.Int64, len: -1,
410 expectConverted: true, converted: ConvertedTypes.Int64, expectLogical: true, checkLogical: checkInt,
411 },
412 }
413 for _, tt := range tests {
414 s.Run(tt.name, func() {
415 t := s.reconstructInteger(tt)
416 s.inspectInt(t)
417 })
418 }
419 }
420
421 func TestSchemaElementNestedSerialization(t *testing.T) {
422
423
424
425 strNode := MustPrimitive(NewPrimitiveNodeLogical("string" , parquet.Repetitions.Required, StringLogicalType{}, parquet.Types.ByteArray, -1 , -1 ))
426 dateNode := MustPrimitive(NewPrimitiveNodeLogical("date" , parquet.Repetitions.Required, DateLogicalType{}, parquet.Types.Int32, -1 , -1 ))
427 jsonNode := MustPrimitive(NewPrimitiveNodeLogical("json" , parquet.Repetitions.Required, JSONLogicalType{}, parquet.Types.ByteArray, -1 , -1 ))
428 uuidNode := MustPrimitive(NewPrimitiveNodeLogical("uuid" , parquet.Repetitions.Required, UUIDLogicalType{}, parquet.Types.FixedLenByteArray, 16 , - 1))
429 timestampNode := MustPrimitive(NewPrimitiveNodeLogical("timestamp" , parquet.Repetitions.Required, NewTimestampLogicalType(false , TimeUnitNanos), parquet.Types.Int64, -1 , -1 ))
430 intNode := MustPrimitive(NewPrimitiveNodeLogical("int" , parquet.Repetitions.Required, NewIntLogicalType(64 , false ), parquet.Types.Int64, -1 , -1 ))
431 decimalNode := MustPrimitive(NewPrimitiveNodeLogical("decimal" , parquet.Repetitions.Required, NewDecimalLogicalType(16 , 6 ), parquet.Types.Int64, -1 , -1 ))
432 float16Node := MustPrimitive(NewPrimitiveNodeLogical("float16" , parquet.Repetitions.Required, Float16LogicalType{}, parquet.Types.FixedLenByteArray, 2 , - 1))
433 listNode := MustGroup(NewGroupNodeLogical("list" , parquet.Repetitions.Repeated, []Node{strNode, dateNode, jsonNode, uuidNode, timestampNode, intNode, decimalNode, float16Node}, NewListLogicalType(), -1 ))
434
435 listElems := ToThrift(listNode)
436 assert.Equal(t, "list", listElems[0].Name)
437 assert.True(t, listElems[0].IsSetConvertedType())
438 assert.True(t, listElems[0].IsSetLogicalType())
439 assert.Equal(t, format.ConvertedType(ConvertedTypes.List), listElems[0].GetConvertedType())
440 assert.True(t, listElems[0].LogicalType.IsSetLIST())
441 assert.True(t, listElems[1].LogicalType.IsSetSTRING())
442 assert.True(t, listElems[2].LogicalType.IsSetDATE())
443 assert.True(t, listElems[3].LogicalType.IsSetJSON())
444 assert.True(t, listElems[4].LogicalType.IsSetUUID())
445 assert.True(t, listElems[5].LogicalType.IsSetTIMESTAMP())
446 assert.True(t, listElems[6].LogicalType.IsSetINTEGER())
447 assert.True(t, listElems[7].LogicalType.IsSetDECIMAL())
448 assert.True(t, listElems[8].LogicalType.IsSetFLOAT16())
449
450 mapNode := MustGroup(NewGroupNodeLogical("map" , parquet.Repetitions.Required, []Node{}, MapLogicalType{}, -1 ))
451 mapElems := ToThrift(mapNode)
452 assert.Equal(t, "map", mapElems[0].Name)
453 assert.True(t, mapElems[0].IsSetConvertedType())
454 assert.True(t, mapElems[0].IsSetLogicalType())
455 assert.Equal(t, format.ConvertedType(ConvertedTypes.Map), mapElems[0].GetConvertedType())
456 assert.True(t, mapElems[0].LogicalType.IsSetMAP())
457 }
458
459 func TestLogicalTypeSerializationRoundTrip(t *testing.T) {
460 tests := []struct {
461 name string
462 logical LogicalType
463 physical parquet.Type
464 len int
465 }{
466 {"string", StringLogicalType{}, parquet.Types.ByteArray, -1},
467 {"enum", EnumLogicalType{}, parquet.Types.ByteArray, -1},
468 {"decimal", NewDecimalLogicalType(16, 6), parquet.Types.Int64, -1},
469 {"date", DateLogicalType{}, parquet.Types.Int32, -1},
470 {"time_T_ms", NewTimeLogicalType(true, TimeUnitMillis), parquet.Types.Int32, -1},
471 {"time_T_us", NewTimeLogicalType(true, TimeUnitMicros), parquet.Types.Int64, -1},
472 {"time_T_ns", NewTimeLogicalType(true, TimeUnitNanos), parquet.Types.Int64, -1},
473 {"time_F_ms", NewTimeLogicalType(false, TimeUnitMillis), parquet.Types.Int32, -1},
474 {"time_F_us", NewTimeLogicalType(false, TimeUnitMicros), parquet.Types.Int64, -1},
475 {"time_F_ns", NewTimeLogicalType(false, TimeUnitNanos), parquet.Types.Int64, -1},
476 {"timestamp_T_ms", NewTimestampLogicalType(true, TimeUnitMillis), parquet.Types.Int64, -1},
477 {"timestamp_T_us", NewTimestampLogicalType(true, TimeUnitMicros), parquet.Types.Int64, -1},
478 {"timestamp_T_ns", NewTimestampLogicalType(true, TimeUnitNanos), parquet.Types.Int64, -1},
479 {"timestamp_F_ms", NewTimestampLogicalType(false, TimeUnitMillis), parquet.Types.Int64, -1},
480 {"timestamp_F_us", NewTimestampLogicalType(false, TimeUnitMicros), parquet.Types.Int64, -1},
481 {"timestamp_F_ns", NewTimestampLogicalType(false, TimeUnitNanos), parquet.Types.Int64, -1},
482 {"interval", IntervalLogicalType{}, parquet.Types.FixedLenByteArray, 12},
483 {"uint8", NewIntLogicalType(8, false), parquet.Types.Int32, -1},
484 {"uint16", NewIntLogicalType(16, false), parquet.Types.Int32, -1},
485 {"uint32", NewIntLogicalType(32, false), parquet.Types.Int32, -1},
486 {"uint64", NewIntLogicalType(64, false), parquet.Types.Int64, -1},
487 {"int8", NewIntLogicalType(8, true), parquet.Types.Int32, -1},
488 {"int16", NewIntLogicalType(16, true), parquet.Types.Int32, -1},
489 {"int32", NewIntLogicalType(32, true), parquet.Types.Int32, -1},
490 {"int64", NewIntLogicalType(64, true), parquet.Types.Int64, -1},
491 {"null", NullLogicalType{}, parquet.Types.Boolean, -1},
492 {"json", JSONLogicalType{}, parquet.Types.ByteArray, -1},
493 {"bson", BSONLogicalType{}, parquet.Types.ByteArray, -1},
494 {"uuid", UUIDLogicalType{}, parquet.Types.FixedLenByteArray, 16},
495 {"float16", Float16LogicalType{}, parquet.Types.FixedLenByteArray, 2},
496 {"none", NoLogicalType{}, parquet.Types.Boolean, -1},
497 }
498
499 for _, tt := range tests {
500 t.Run(tt.name, func(t *testing.T) {
501 n := MustPrimitive(NewPrimitiveNodeLogical("something" , parquet.Repetitions.Required, tt.logical, tt.physical, tt.len, -1 ))
502 elem := n.toThrift()
503 recover := MustPrimitive(PrimitiveNodeFromThrift(elem))
504 assert.True(t, n.Equals(recover))
505 })
506 }
507
508 n := MustGroup(NewGroupNodeLogical("map" , parquet.Repetitions.Required, []Node{}, MapLogicalType{}, -1 ))
509 elem := n.toThrift()
510 recover := MustGroup(GroupNodeFromThrift(elem, []Node{}))
511 assert.True(t, recover.Equals(n))
512
513 n = MustGroup(NewGroupNodeLogical("list" , parquet.Repetitions.Required, []Node{}, ListLogicalType{}, -1 ))
514 elem = n.toThrift()
515 recover = MustGroup(GroupNodeFromThrift(elem, []Node{}))
516 assert.True(t, recover.Equals(n))
517 }
518
519 func TestSchemaElementConstruction(t *testing.T) {
520 suite.Run(t, new(SchemaElementConstructionSuite))
521 }
522
View as plain text