mirror of
https://github.com/hanzo-ds/native.git
synced 2026-10-30 20:00:34 +00:00
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.
320 lines
6.3 KiB
Go
320 lines
6.3 KiB
Go
package proto
|
|
|
|
import (
|
|
"github.com/go-faster/errors"
|
|
"github.com/segmentio/asm/bswap"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
//go:generate go run github.com/dmarkham/enumer -type Interface -trimprefix Interface -output client_info_interface_enum.go
|
|
|
|
// Interface is interface of client.
|
|
type Interface byte
|
|
|
|
// Possible interfaces.
|
|
const (
|
|
InterfaceTCP Interface = 1
|
|
InterfaceHTTP Interface = 2
|
|
)
|
|
|
|
//go:generate go run github.com/dmarkham/enumer -type ClientQueryKind -trimprefix ClientQueryKind -output client_info_query_enum.go
|
|
|
|
// ClientQueryKind is kind of query.
|
|
type ClientQueryKind byte
|
|
|
|
// Possible query kinds.
|
|
const (
|
|
ClientQueryNone ClientQueryKind = 0
|
|
ClientQueryInitial ClientQueryKind = 1
|
|
ClientQuerySecondary ClientQueryKind = 2
|
|
)
|
|
|
|
// ClientInfo message.
|
|
type ClientInfo struct {
|
|
ProtocolVersion int
|
|
|
|
Major int
|
|
Minor int
|
|
Patch int
|
|
|
|
Interface Interface
|
|
Query ClientQueryKind
|
|
|
|
InitialUser string
|
|
InitialQueryID string
|
|
InitialAddress string
|
|
InitialTime int64
|
|
|
|
OSUser string
|
|
ClientHostname string
|
|
ClientName string
|
|
|
|
Span trace.SpanContext
|
|
|
|
QuotaKey string
|
|
DistributedDepth int
|
|
|
|
// For parallel processing on replicas.
|
|
|
|
CollaborateWithInitiator bool
|
|
CountParticipatingReplicas int
|
|
NumberOfCurrentReplica int
|
|
}
|
|
|
|
// EncodeAware encodes to buffer version-aware.
|
|
func (c ClientInfo) EncodeAware(b *Buffer, version int) {
|
|
b.PutByte(byte(c.Query))
|
|
|
|
b.PutString(c.InitialUser)
|
|
b.PutString(c.InitialQueryID)
|
|
b.PutString(c.InitialAddress)
|
|
if FeatureQueryStartTime.In(version) {
|
|
b.PutInt64(c.InitialTime)
|
|
}
|
|
|
|
b.PutByte(byte(c.Interface))
|
|
|
|
b.PutString(c.OSUser)
|
|
b.PutString(c.ClientHostname)
|
|
b.PutString(c.ClientName)
|
|
|
|
b.PutInt(c.Major)
|
|
b.PutInt(c.Minor)
|
|
b.PutInt(c.ProtocolVersion)
|
|
|
|
if FeatureQuotaKeyInClientInfo.In(version) {
|
|
b.PutString(c.QuotaKey)
|
|
}
|
|
if FeatureDistributedDepth.In(version) {
|
|
b.PutInt(c.DistributedDepth)
|
|
}
|
|
if FeatureVersionPatch.In(version) && c.Interface == InterfaceTCP {
|
|
b.PutInt(c.Patch)
|
|
}
|
|
if FeatureOpenTelemetry.In(version) {
|
|
if c.Span.IsValid() {
|
|
b.PutByte(1)
|
|
{
|
|
v := c.Span.TraceID()
|
|
start := len(b.Buf)
|
|
b.Buf = append(b.Buf, v[:]...)
|
|
bswap.Swap64(b.Buf[start:])
|
|
}
|
|
{
|
|
v := c.Span.SpanID()
|
|
start := len(b.Buf)
|
|
b.Buf = append(b.Buf, v[:]...)
|
|
bswap.Swap64(b.Buf[start:])
|
|
}
|
|
b.PutString(c.Span.TraceState().String())
|
|
b.PutByte(byte(c.Span.TraceFlags()))
|
|
} else {
|
|
// No OTEL data.
|
|
b.PutByte(0)
|
|
}
|
|
}
|
|
if FeatureParallelReplicas.In(version) {
|
|
if c.CollaborateWithInitiator {
|
|
b.PutInt(1)
|
|
} else {
|
|
b.PutInt(0)
|
|
}
|
|
b.PutInt(c.CountParticipatingReplicas)
|
|
b.PutInt(c.NumberOfCurrentReplica)
|
|
}
|
|
}
|
|
|
|
func (c *ClientInfo) DecodeAware(r *Reader, version int) error {
|
|
{
|
|
v, err := r.UInt8()
|
|
if err != nil {
|
|
return errors.Wrap(err, "query kind")
|
|
}
|
|
c.Query = ClientQueryKind(v)
|
|
if !c.Query.IsAClientQueryKind() {
|
|
return errors.Errorf("unknown query kind %d", v)
|
|
}
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "initial user")
|
|
}
|
|
c.InitialUser = v
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "initial query id")
|
|
}
|
|
c.InitialQueryID = v
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "initial address")
|
|
}
|
|
c.InitialAddress = v
|
|
}
|
|
|
|
if FeatureQueryStartTime.In(version) {
|
|
// Microseconds.
|
|
v, err := r.Int64()
|
|
if err != nil {
|
|
return errors.Wrap(err, "query start time")
|
|
}
|
|
c.InitialTime = v
|
|
}
|
|
|
|
{
|
|
v, err := r.UInt8()
|
|
if err != nil {
|
|
return errors.Wrap(err, "interface")
|
|
}
|
|
c.Interface = Interface(v)
|
|
if !c.Interface.IsAInterface() {
|
|
return errors.Errorf("unknown interface %d", v)
|
|
}
|
|
|
|
// TODO(ernado): support HTTP
|
|
if c.Interface != InterfaceTCP {
|
|
return errors.New("only tcp interface is supported")
|
|
}
|
|
}
|
|
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "os user")
|
|
}
|
|
c.OSUser = v
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "client hostname")
|
|
}
|
|
c.ClientHostname = v
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "client name")
|
|
}
|
|
c.ClientName = v
|
|
}
|
|
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "major version")
|
|
}
|
|
c.Major = v
|
|
}
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "minor version")
|
|
}
|
|
c.Minor = v
|
|
}
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "protocol version")
|
|
}
|
|
c.ProtocolVersion = v
|
|
}
|
|
|
|
if FeatureQuotaKeyInClientInfo.In(version) {
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "quota key")
|
|
}
|
|
c.QuotaKey = v
|
|
}
|
|
if FeatureDistributedDepth.In(version) {
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "distributed depth")
|
|
}
|
|
c.DistributedDepth = v
|
|
}
|
|
if FeatureVersionPatch.In(version) && c.Interface == InterfaceTCP {
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "patch version")
|
|
}
|
|
c.Patch = v
|
|
}
|
|
if FeatureOpenTelemetry.In(version) {
|
|
hasTrace, err := r.Bool()
|
|
if err != nil {
|
|
return errors.Wrap(err, "open telemetry start")
|
|
}
|
|
if hasTrace {
|
|
var cfg trace.SpanContextConfig
|
|
{
|
|
v, err := r.ReadRaw(len(cfg.TraceID))
|
|
if err != nil {
|
|
return errors.Wrap(err, "trace id")
|
|
}
|
|
bswap.Swap64(v)
|
|
copy(cfg.TraceID[:], v)
|
|
}
|
|
{
|
|
v, err := r.ReadRaw(len(cfg.SpanID))
|
|
if err != nil {
|
|
return errors.Wrap(err, "span id")
|
|
}
|
|
bswap.Swap64(v)
|
|
copy(cfg.SpanID[:], v)
|
|
}
|
|
{
|
|
v, err := r.Str()
|
|
if err != nil {
|
|
return errors.Wrap(err, "trace state")
|
|
}
|
|
state, err := trace.ParseTraceState(v)
|
|
if err != nil {
|
|
return errors.Wrap(err, "parse trace state")
|
|
}
|
|
cfg.TraceState = state
|
|
}
|
|
{
|
|
v, err := r.Byte()
|
|
if err != nil {
|
|
return errors.Wrap(err, "trace flag")
|
|
}
|
|
cfg.TraceFlags = trace.TraceFlags(v)
|
|
}
|
|
c.Span = trace.NewSpanContext(cfg)
|
|
}
|
|
}
|
|
if FeatureParallelReplicas.In(version) {
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "parallel replicas")
|
|
}
|
|
c.CollaborateWithInitiator = v == 1
|
|
}
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "count participating replicas")
|
|
}
|
|
c.CountParticipatingReplicas = v
|
|
}
|
|
{
|
|
v, err := r.Int()
|
|
if err != nil {
|
|
return errors.Wrap(err, "number of current replica")
|
|
}
|
|
c.NumberOfCurrentReplica = v
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|