package builder

import (
	
	

	
	
	
)

// The code in this file is based heavily on Apache arrow's array.RecordBuilder,
// with some modifications to use our own optimized record builders. Ideally, we
// would eventually merge this upstream.

// RecordBuilder eases the process of building a Record, iteratively, from
// a known Schema.
type RecordBuilder struct {
	refCount int64
	mem      memory.Allocator
	schema   *arrow.Schema
	fields   []ColumnBuilder
}

// NewRecordBuilder returns a builder, using the provided memory allocator and a schema.
func ( memory.Allocator,  *arrow.Schema) *RecordBuilder {
	 := &RecordBuilder{
		refCount: 1,
		mem:      ,
		schema:   ,
		fields:   make([]ColumnBuilder, .NumFields()),
	}

	for  := 0;  < .NumFields(); ++ {
		.fields[] = NewBuilder(, .Field().Type)
	}

	return 
}

// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func ( *RecordBuilder) () {
	atomic.AddInt64(&.refCount, 1)
}

// Release decreases the reference count by 1.
func ( *RecordBuilder) () {
	if atomic.AddInt64(&.refCount, -1) == 0 {
		for ,  := range .fields {
			.Release()
		}
		.fields = nil
	}
}

func ( *RecordBuilder) () *arrow.Schema     { return .schema }
func ( *RecordBuilder) () []ColumnBuilder   { return .fields }
func ( *RecordBuilder) ( int) ColumnBuilder { return .fields[] }

func ( *RecordBuilder) ( int) {
	for ,  := range .fields {
		.Reserve()
	}
}

// NewRecord creates a new record from the memory buffers and resets the
// RecordBuilder so it can be used to build a new record.
//
// The returned Record must be Release()'d after use.
//
// NewRecord panics if the fields' builder do not have the same length.
func ( *RecordBuilder) () arrow.Record {
	 := make([]arrow.Array, len(.fields))
	 := int64(0)

	defer func( []arrow.Array) {
		for ,  := range  {
			if  == nil {
				continue
			}
			.Release()
		}
	}()

	for ,  := range .fields {
		[] = .NewArray()
		 := int64([].Len())
		if  > 0 &&  !=  {
			panic(fmt.Errorf("arrow/array: field %d has %d rows. want=%d", , , ))
		}
		 = 
	}

	return array.NewRecord(.schema, , )
}

// ExpandSchema expands the record builder schema by adding new fields.
func ( *RecordBuilder) ( *arrow.Schema) {
	for  := 0;  < .NumFields(); ++ {
		 := .Field()
		 := false
		for  := 0;  < .schema.NumFields(); ++ {
			 := .schema.Field()
			if .Equal() {
				 = true
				break
			}
		}
		if  { // field already exists
			continue
		}

		// Add the new field
		.fields = append(.fields[:], append([]ColumnBuilder{NewBuilder(.mem, .Type)}, .fields[:]...)...)
	}

	.schema = 
}

// Reset will call ResetFull on any dictionary builders to prevent memo tables from growing unbounded.
func ( *RecordBuilder) () {
	for ,  := range .fields {
		if ,  := .(*ListBuilder);  {
			if ,  := .ValueBuilder().(array.DictionaryBuilder);  {
				.ResetFull()
			}
		}
	}
}