Files
zeekay 765c3d0aa1 hanzo-ds/native: de-branded native protocol lib (fork of clickhouse ch-go v0.71.0)
Module path, package names, and identifiers de-branded to native/proto/compress/
pool/tracing. Server wire-protocol strings preserved. Vendored codec surface used
by hanzo-ds/go (proto + compress).
2026-07-10 13:10:07 -07:00

225 lines
4.9 KiB
Go

package proto
import (
"encoding/binary"
"github.com/go-faster/errors"
)
type Position struct {
Start int
End int
}
// ColStr represents String column.
//
// Use ColBytes for []bytes ColumnOf implementation.
type ColStr struct {
Buf []byte
Pos []Position
}
// Append string to column.
func (c *ColStr) Append(v string) {
start := len(c.Buf)
c.Buf = append(c.Buf, v...)
end := len(c.Buf)
c.Pos = append(c.Pos, Position{Start: start, End: end})
}
// AppendBytes append byte slice as string to column.
func (c *ColStr) AppendBytes(v []byte) {
start := len(c.Buf)
c.Buf = append(c.Buf, v...)
end := len(c.Buf)
c.Pos = append(c.Pos, Position{Start: start, End: end})
}
func (c *ColStr) AppendArr(v []string) {
for _, e := range v {
c.Append(e)
}
}
// Compile-time assertions for ColStr.
var (
_ ColInput = ColStr{}
_ ColResult = (*ColStr)(nil)
_ Column = (*ColStr)(nil)
_ ColumnOf[string] = (*ColStr)(nil)
_ Arrayable[string] = (*ColStr)(nil)
)
// Type returns ColumnType of String.
func (ColStr) Type() ColumnType {
return ColumnTypeString
}
// Rows returns count of rows in column.
func (c ColStr) Rows() int {
return len(c.Pos)
}
// Reset resets data in row, preserving capacity for efficiency.
func (c *ColStr) Reset() {
c.Buf = c.Buf[:0]
c.Pos = c.Pos[:0]
}
// EncodeColumn encodes String rows to *Buffer.
func (c ColStr) EncodeColumn(b *Buffer) {
var buf [binary.MaxVarintLen64]byte
for _, p := range c.Pos {
length := uint64(p.End - p.Start)
// Encode to temp buffer first
n := binary.PutUvarint(buf[:], length)
// Append only the bytes we need
b.Buf = append(b.Buf, buf[:n]...)
b.Buf = append(b.Buf, c.Buf[p.Start:p.End]...)
}
}
// WriteColumn writes String rows to *Writer.
func (c ColStr) WriteColumn(w *Writer) {
var buf [binary.MaxVarintLen64]byte
// Writing values from c.Buf directly might improve performance if [ColStr] contains a few rows of very long strings.
// However, most of the time it is quite opposite, so we copy data.
w.ChainBuffer(func(b *Buffer) {
for _, p := range c.Pos {
n := binary.PutUvarint(buf[:], uint64(p.End-p.Start))
b.PutRaw(buf[:n])
b.PutRaw(c.Buf[p.Start:p.End])
}
})
}
// ForEach calls f on each string from column.
func (c ColStr) ForEach(f func(i int, s string) error) error {
return c.ForEachBytes(func(i int, b []byte) error {
return f(i, string(b))
})
}
// First returns first row of column.
func (c ColStr) First() string {
return c.Row(0)
}
// Row returns row with number i.
func (c ColStr) Row(i int) string {
p := c.Pos[i]
return string(c.Buf[p.Start:p.End])
}
// RowBytes returns row with number i as byte slice.
func (c ColStr) RowBytes(i int) []byte {
p := c.Pos[i]
return c.Buf[p.Start:p.End]
}
// ForEachBytes calls f on each string from column as byte slice.
func (c ColStr) ForEachBytes(f func(i int, b []byte) error) error {
for i, p := range c.Pos {
if err := f(i, c.Buf[p.Start:p.End]); err != nil {
return err
}
}
return nil
}
// DecodeColumn decodes String rows from *Reader.
func (c *ColStr) DecodeColumn(r *Reader, rows int) error {
var p Position
size := len(c.Pos)
if cap(c.Pos) < size+rows {
c.Pos = append(c.Pos, make([]Position, size+rows-cap(c.Pos))...)
}
c.Pos = c.Pos[:0]
c.Buf = c.Buf[:cap(c.Buf)]
for i := 0; i < rows; i++ {
n, err := r.StrLen()
if err != nil {
return errors.Wrapf(err, "row %d: read length", i)
}
p.Start = p.End
p.End += n
if len(c.Buf) < p.End {
var an int
if n < 128 {
// small size, do batch buffer alloc
an = n * (rows - i)
} else {
an = n
}
c.Buf = append(c.Buf, make([]byte, an)...)
}
if err := r.ReadFull(c.Buf[p.Start:p.End]); err != nil {
return errors.Wrapf(err, "row %d: read full", i)
}
c.Pos = append(c.Pos, p)
}
c.Buf = c.Buf[:p.End]
return nil
}
// LowCardinality returns LowCardinality(String).
func (c *ColStr) LowCardinality() *ColLowCardinality[string] {
return &ColLowCardinality[string]{
index: c,
}
}
// Array is helper that creates Array(String).
func (c *ColStr) Array() *ColArr[string] {
return &ColArr[string]{
Data: c,
}
}
// Nullable is helper that creates Nullable(String).
func (c *ColStr) Nullable() *ColNullable[string] {
return &ColNullable[string]{
Values: c,
}
}
// ColBytes is ColStr wrapper to be ColumnOf for []byte.
type ColBytes struct {
ColStr
}
// Row returns row with number i.
func (c ColBytes) Row(i int) []byte {
return c.RowBytes(i)
}
// Append byte slice to column.
func (c *ColBytes) Append(v []byte) {
c.AppendBytes(v)
}
// AppendArr append slice of byte slices to column.
func (c *ColBytes) AppendArr(v [][]byte) {
for _, s := range v {
c.Append(s)
}
}
// Array is helper that creates Array(String).
func (c *ColBytes) Array() *ColArr[[]byte] {
return &ColArr[[]byte]{
Data: c,
}
}
// Nullable is helper that creates Nullable(String).
func (c *ColBytes) Nullable() *ColNullable[[]byte] {
return &ColNullable[[]byte]{
Values: c,
}
}