Files
zeekay ef352c1051 debrand: rename the wire client name, prose and linter config
proto.Name is sent in ClientHello and lands in the server's system.query_log,
so it is wire visible; it now reads datastore/native and is covered by a test.
Verified against the live server: the handshake succeeds and the new name
appears in query_log.

goimports' local-prefixes still named the upstream module, so it was not
grouping this module's own imports.

Doc comments, the deprecated-error markers in proto/error_codes.go and the
package prose are swept. Dead references are removed rather than repointed:
go-faster.org/docs/clickhouse and the mangled Datastore/clickhouse-cpp link
both 404, and the list of other vendors' clients does not belong here.

Four things deliberately keep the vendor name, and CI records why:
LICENSE and AUTHORS are the copyright notices Apache-2.0 requires; db.system in
query.go is an OpenTelemetry enum whose registered value for this DBMS is fixed
by the specification, so emitting anything else would be non-conformant; and
README names clickhouse-local, which is genuinely the binary our own server
image ships.

Numeric error codes and protocol revision constants are untouched.
2026-07-26 11:50:36 -07:00

305 lines
6.3 KiB
Go

package proto
import (
"bufio"
"encoding/binary"
"io"
"math"
"github.com/go-faster/errors"
"github.com/hanzo-ds/native/compress"
)
// Decoder implements decoding from Reader.
type Decoder interface {
Decode(r *Reader) error
}
// AwareDecoder implements encoding to Buffer that depends on version.
type AwareDecoder interface {
DecodeAware(r *Reader, version int) error
}
// Reader implements Datastore protocol decoding from buffered reader.
// Not goroutine-safe.
type Reader struct {
raw *bufio.Reader // raw bytes, e.g. on the wire
data io.Reader // data, decompressed or same as raw
b *Buffer // internal buffer
decompressed io.Reader // decompressed data stream, from raw
}
func (r *Reader) ReadByte() (byte, error) {
if err := r.readFull(1); err != nil {
return 0, err
}
return r.b.Buf[0], nil
}
// EnableCompression makes next reads use decompressed source of data.
func (r *Reader) EnableCompression() {
r.data = r.decompressed
}
// DisableCompression makes next read use raw source of data.
func (r *Reader) DisableCompression() {
r.data = r.raw
}
func (r *Reader) Read(p []byte) (n int, err error) {
return r.data.Read(p)
}
// Decode value.
func (r *Reader) Decode(v Decoder) error {
return v.Decode(r)
}
func (r *Reader) ReadFull(buf []byte) error {
if _, err := io.ReadFull(r, buf); err != nil {
return errors.Wrap(err, "read")
}
return nil
}
func (r *Reader) readFull(n int) error {
r.b.Ensure(n)
return r.ReadFull(r.b.Buf)
}
// ReadRaw reads raw n bytes.
func (r *Reader) ReadRaw(n int) ([]byte, error) {
if err := r.readFull(n); err != nil {
return nil, errors.Wrap(err, "read full")
}
return r.b.Buf, nil
}
// UVarInt reads uint64 from internal reader.
func (r *Reader) UVarInt() (uint64, error) {
n, err := binary.ReadUvarint(r)
if err != nil {
return 0, errors.Wrap(err, "read")
}
return n, nil
}
// VarInt reads signed int64 from internal reader.
func (r *Reader) VarInt() (int64, error) {
n, err := binary.ReadVarint(r)
if err != nil {
return 0, errors.Wrap(err, "read")
}
return n, nil
}
func (r *Reader) StrLen() (int, error) {
n, err := r.Int()
if err != nil {
return 0, errors.Wrap(err, "read length")
}
if n < 0 {
return 0, errors.Errorf("size %d is invalid", n)
}
return n, nil
}
// StrRaw decodes string to internal buffer and returns it directly.
//
// Do not retain returned slice.
func (r *Reader) StrRaw() ([]byte, error) {
n, err := r.StrLen()
if err != nil {
return nil, errors.Wrap(err, "read length")
}
r.b.Ensure(n)
if _, err := io.ReadFull(r.data, r.b.Buf); err != nil {
return nil, errors.Wrap(err, "read str")
}
return r.b.Buf, nil
}
// StrAppend decodes string and appends it to provided buf.
func (r *Reader) StrAppend(buf []byte) ([]byte, error) {
defer r.b.Reset()
str, err := r.StrRaw()
if err != nil {
return nil, errors.Wrap(err, "raw")
}
return append(buf, str...), nil
}
// StrBytes decodes string and allocates new byte slice with result.
func (r *Reader) StrBytes() ([]byte, error) {
return r.StrAppend(nil)
}
// Str decodes string.
func (r *Reader) Str() (string, error) {
defer r.b.Reset()
// call StrRaw instead of StrBytes and converting
// so we can avoid a second allocation and copy of
// the str/[]byte data
str, err := r.StrRaw()
if err != nil {
return "", errors.Wrap(err, "raw")
}
return string(str), err
}
// Int decodes uvarint as int.
func (r *Reader) Int() (int, error) {
n, err := r.UVarInt()
if err != nil {
return 0, errors.Wrap(err, "uvarint")
}
return int(n), nil
}
// Int8 decodes int8 value.
func (r *Reader) Int8() (int8, error) {
v, err := r.UInt8()
if err != nil {
return 0, err
}
return int8(v), nil
}
// Int16 decodes int16 value.
func (r *Reader) Int16() (int16, error) {
v, err := r.UInt16()
if err != nil {
return 0, err
}
return int16(v), nil
}
// Int32 decodes int32 value.
func (r *Reader) Int32() (int32, error) {
v, err := r.UInt32()
if err != nil {
return 0, err
}
return int32(v), nil
}
// Int64 decodes int64 value.
func (r *Reader) Int64() (int64, error) {
v, err := r.UInt64()
if err != nil {
return 0, err
}
return int64(v), nil
}
// Int128 decodes Int128 value.
func (r *Reader) Int128() (Int128, error) {
v, err := r.UInt128()
if err != nil {
return Int128{}, err
}
return Int128(v), nil
}
// Byte decodes byte value.
func (r *Reader) Byte() (byte, error) {
return r.UInt8()
}
// UInt8 decodes uint8 value.
func (r *Reader) UInt8() (uint8, error) {
if err := r.readFull(1); err != nil {
return 0, errors.Wrap(err, "read")
}
return r.b.Buf[0], nil
}
// UInt16 decodes uint16 value.
func (r *Reader) UInt16() (uint16, error) {
if err := r.readFull(2); err != nil {
return 0, errors.Wrap(err, "read")
}
return binary.LittleEndian.Uint16(r.b.Buf), nil
}
// UInt32 decodes uint32 value.
func (r *Reader) UInt32() (uint32, error) {
if err := r.readFull(32 / 8); err != nil {
return 0, errors.Wrap(err, "read")
}
return binary.LittleEndian.Uint32(r.b.Buf), nil
}
// UInt64 decodes uint64 value.
func (r *Reader) UInt64() (uint64, error) {
if err := r.readFull(64 / 8); err != nil {
return 0, errors.Wrap(err, "read")
}
return binary.LittleEndian.Uint64(r.b.Buf), nil
}
// UInt128 decodes UInt128 value.
func (r *Reader) UInt128() (UInt128, error) {
if err := r.readFull(128 / 8); err != nil {
return UInt128{}, errors.Wrap(err, "read")
}
return binUInt128(r.b.Buf), nil
}
// Float32 decodes float32 value.
func (r *Reader) Float32() (float32, error) {
v, err := r.UInt32()
if err != nil {
return 0, errors.Wrap(err, "bits")
}
return math.Float32frombits(v), nil
}
// Float64 decodes float64 value.
func (r *Reader) Float64() (float64, error) {
v, err := r.UInt64()
if err != nil {
return 0, errors.Wrap(err, "bits")
}
return math.Float64frombits(v), nil
}
// Bool decodes bool as uint8.
func (r *Reader) Bool() (bool, error) {
v, err := r.UInt8()
if err != nil {
return false, errors.Wrap(err, "uint8")
}
switch v {
case boolTrue:
return true, nil
case boolFalse:
return false, nil
default:
return false, errors.Errorf("unexpected value %d for boolean", v)
}
}
const defaultReaderSize = 1024 * 128 // 128kb
// NewReader initializes new Reader from provided io.Reader.
func NewReader(r io.Reader) *Reader {
c := bufio.NewReaderSize(r, defaultReaderSize)
return &Reader{
raw: c,
data: c,
b: &Buffer{},
decompressed: compress.NewReader(c),
}
}