// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package array import ( "bytes" "fmt" "reflect" "strings" "sync/atomic" "github.com/apache/arrow/go/v10/arrow" "github.com/apache/arrow/go/v10/arrow/internal/debug" "github.com/apache/arrow/go/v10/arrow/memory" "github.com/goccy/go-json" ) // Null represents an immutable, degenerate array with no physical storage. type Null struct { array } // NewNull returns a new Null array value of size n. func NewNull(n int) *Null { a := &Null{} a.refCount = 1 data := NewData( arrow.Null, n, []*memory.Buffer{nil}, nil, n, 0, ) a.setData(data) data.Release() return a } // NewNullData returns a new Null array value, from data. func NewNullData(data arrow.ArrayData) *Null { a := &Null{} a.refCount = 1 a.setData(data.(*Data)) return a } func (a *Null) String() string { o := new(strings.Builder) o.WriteString("[") for i := 0; i < a.Len(); i++ { if i > 0 { o.WriteString(" ") } o.WriteString("(null)") } o.WriteString("]") return o.String() } func (a *Null) setData(data *Data) { a.array.setData(data) a.array.nullBitmapBytes = nil a.array.data.nulls = a.array.data.length } func (a *Null) getOneForMarshal(i int) interface{} { return nil } func (a *Null) MarshalJSON() ([]byte, error) { return json.Marshal(make([]interface{}, a.Len())) } type NullBuilder struct { builder } // NewNullBuilder returns a builder, using the provided memory allocator. func NewNullBuilder(mem memory.Allocator) *NullBuilder { return &NullBuilder{builder: builder{refCount: 1, mem: mem}} } func (b *NullBuilder) Type() arrow.DataType { return arrow.Null } // Release decreases the reference count by 1. // When the reference count goes to zero, the memory is freed. func (b *NullBuilder) Release() { debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") if atomic.AddInt64(&b.refCount, -1) == 0 { if b.nullBitmap != nil { b.nullBitmap.Release() b.nullBitmap = nil } } } func (b *NullBuilder) AppendNull() { b.builder.length++ b.builder.nulls++ } func (b *NullBuilder) AppendEmptyValue() { b.AppendNull() } func (*NullBuilder) Reserve(size int) {} func (*NullBuilder) Resize(size int) {} func (*NullBuilder) init(cap int) {} func (*NullBuilder) resize(newBits int, init func(int)) {} // NewArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder // so it can be used to build a new array. func (b *NullBuilder) NewArray() arrow.Array { return b.NewNullArray() } // NewNullArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder // so it can be used to build a new array. func (b *NullBuilder) NewNullArray() (a *Null) { data := b.newData() a = NewNullData(data) data.Release() return } func (b *NullBuilder) newData() (data *Data) { data = NewData( arrow.Null, b.length, []*memory.Buffer{nil}, nil, b.nulls, 0, ) b.reset() return } func (b *NullBuilder) unmarshalOne(dec *json.Decoder) error { t, err := dec.Token() if err != nil { return err } switch t.(type) { case nil: b.AppendNull() default: return &json.UnmarshalTypeError{ Value: fmt.Sprint(t), Type: reflect.TypeOf(nil), Offset: dec.InputOffset(), } } return nil } func (b *NullBuilder) unmarshal(dec *json.Decoder) error { for dec.More() { if err := b.unmarshalOne(dec); err != nil { return err } } return nil } func (b *NullBuilder) UnmarshalJSON(data []byte) error { dec := json.NewDecoder(bytes.NewReader(data)) t, err := dec.Token() if err != nil { return err } if delim, ok := t.(json.Delim); !ok || delim != '[' { return fmt.Errorf("null builder must unpack from json array, found %s", delim) } return b.unmarshal(dec) } var ( _ arrow.Array = (*Null)(nil) _ Builder = (*NullBuilder)(nil) )