xtdb.arrow.VariableWidthVector.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xtdb-core Show documentation
Show all versions of xtdb-core Show documentation
An open source document database with bitemporal graph queries
The newest version!
package xtdb.arrow
import org.apache.arrow.memory.ArrowBuf
import org.apache.arrow.memory.BufferAllocator
import org.apache.arrow.memory.util.ArrowBufPointer
import org.apache.arrow.memory.util.hash.ArrowBufHasher
import org.apache.arrow.vector.BaseVariableWidthVector
import org.apache.arrow.vector.ValueVector
import org.apache.arrow.vector.ipc.message.ArrowFieldNode
import org.apache.arrow.vector.types.pojo.ArrowType
import org.apache.arrow.vector.types.pojo.Field
import org.apache.arrow.vector.types.pojo.FieldType
import xtdb.api.query.IKeyFn
import java.nio.ByteBuffer
abstract class VariableWidthVector(allocator: BufferAllocator) : Vector() {
override val field: Field get() = Field(name, FieldType(nullable, arrowType, null), emptyList())
abstract val arrowType: ArrowType
private val validityBuffer = ExtensibleBuffer(allocator)
private val offsetBuffer = ExtensibleBuffer(allocator)
private val dataBuffer = ExtensibleBuffer(allocator)
private var lastOffset: Int = 0
override fun isNull(idx: Int) = !validityBuffer.getBit(idx)
private fun writeOffset(newOffset: Int) {
if (valueCount == 0) offsetBuffer.writeInt(0)
offsetBuffer.writeInt(newOffset)
lastOffset = newOffset
}
override fun writeNull() {
writeOffset(lastOffset)
validityBuffer.writeBit(valueCount++, 0)
}
private fun writeNotNull(len: Int) {
writeOffset(lastOffset + len)
validityBuffer.writeBit(valueCount++, 1)
}
override fun getBytes(idx: Int): ByteBuffer {
val start = offsetBuffer.getInt(idx)
val end = offsetBuffer.getInt(idx + 1)
return dataBuffer.getBytes(start, end - start)
}
override fun writeBytes(buf: ByteBuffer) {
writeNotNull(buf.remaining())
dataBuffer.writeBytes(buf.duplicate())
}
override fun getPointer(idx: Int, reuse: ArrowBufPointer): ArrowBufPointer =
offsetBuffer.getInt(idx).let { start ->
dataBuffer.getPointer(start, offsetBuffer.getInt(idx + 1) - start, reuse)
}
protected fun getByteArray(idx: Int): ByteArray {
val buf = getBytes(idx)
return ByteArray(buf.remaining()).also { buf.duplicate().get(it) }
}
override fun hashCode0(idx: Int, hasher: ArrowBufHasher): Int {
val start = offsetBuffer.getInt(idx).toLong()
val end = offsetBuffer.getInt(idx + 1).toLong()
return dataBuffer.hashCode(hasher, start, end - start)
}
override fun rowCopier0(src: VectorReader): RowCopier {
require(src is VariableWidthVector)
return RowCopier { srcIdx ->
val start = src.offsetBuffer.getInt(srcIdx).toLong()
val len = src.offsetBuffer.getInt(srcIdx + 1) - start
dataBuffer.writeBytes(src.dataBuffer, start, len)
valueCount.also { writeNotNull(len.toInt()) }
}
}
override fun unloadBatch(nodes: MutableList, buffers: MutableList) {
nodes.add(ArrowFieldNode(valueCount.toLong(), -1))
validityBuffer.unloadBuffer(buffers)
offsetBuffer.unloadBuffer(buffers)
dataBuffer.unloadBuffer(buffers)
}
override fun loadBatch(nodes: MutableList, buffers: MutableList) {
val node = nodes.removeFirstOrNull() ?: error("missing node")
validityBuffer.loadBuffer(buffers.removeFirstOrNull() ?: error("missing validity buffer"))
offsetBuffer.loadBuffer(buffers.removeFirstOrNull() ?: error("missing offset buffer"))
dataBuffer.loadBuffer(buffers.removeFirst() ?: error("missing data buffer"))
valueCount = node.length
}
override fun loadFromArrow(vec: ValueVector) {
require(vec is BaseVariableWidthVector)
validityBuffer.loadBuffer(vec.validityBuffer)
offsetBuffer.loadBuffer(vec.offsetBuffer)
dataBuffer.loadBuffer(vec.dataBuffer)
}
override fun clear() {
validityBuffer.clear()
offsetBuffer.clear()
dataBuffer.clear()
valueCount = 0
lastOffset = 0
}
override fun close() {
validityBuffer.close()
offsetBuffer.close()
dataBuffer.close()
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy