mirror of
https://github.com/hanzo-ds/go.git
synced 2026-10-30 19:45:01 +00:00
Feature-complete v2.44.0 (lib/churl, lib/col, BFloat16, QBit, scanTypeDuration, Options.Logger *slog.Logger) — fixes the [email protected].0 downgrade RED caught. Package datastore, module github.com/hanzo-ds/go, depends only on hanzo-ds/native. Wire strings preserved VERBATIM (X-ClickHouse-* headers, sql.Register("clickhouse"), clickhouse:// DSN, ClientName="clickhouse-go") — consistent with native.
368 lines
7.2 KiB
Go
368 lines
7.2 KiB
Go
package column
|
|
|
|
import (
|
|
"database/sql"
|
|
"database/sql/driver"
|
|
"fmt"
|
|
"github.com/hanzo-ds/native/proto"
|
|
"net"
|
|
"net/netip"
|
|
"reflect"
|
|
)
|
|
|
|
type IPv6 struct {
|
|
col proto.ColIPv6
|
|
name string
|
|
}
|
|
|
|
func (col *IPv6) Reset() {
|
|
col.col.Reset()
|
|
}
|
|
|
|
func (col *IPv6) Name() string {
|
|
return col.name
|
|
}
|
|
|
|
func (col *IPv6) Type() Type {
|
|
return "IPv6"
|
|
}
|
|
|
|
func (col *IPv6) ScanType() reflect.Type {
|
|
return scanTypeIP
|
|
}
|
|
|
|
func (col *IPv6) Rows() int {
|
|
return col.col.Rows()
|
|
}
|
|
|
|
func (col *IPv6) Row(i int, ptr bool) any {
|
|
value := col.row(i)
|
|
if ptr {
|
|
return &value
|
|
}
|
|
return value
|
|
}
|
|
|
|
func (col *IPv6) ScanRow(dest any, row int) error {
|
|
switch d := dest.(type) {
|
|
case *string:
|
|
*d = col.row(row).String()
|
|
case **string:
|
|
*d = new(string)
|
|
**d = col.row(row).String()
|
|
case *net.IP:
|
|
*d = col.row(row)
|
|
case **net.IP:
|
|
*d = new(net.IP)
|
|
**d = col.row(row)
|
|
case *netip.Addr:
|
|
*d = col.rowAddr(row)
|
|
case **netip.Addr:
|
|
*d = new(netip.Addr)
|
|
**d = col.rowAddr(row)
|
|
case *[]byte:
|
|
*d = col.row(row)
|
|
case **[]byte:
|
|
*d = new([]byte)
|
|
**d = col.row(row)
|
|
case *proto.IPv6:
|
|
*d = col.col.Row(row)
|
|
case **proto.IPv6:
|
|
*d = new(proto.IPv6)
|
|
**d = col.col.Row(row)
|
|
case *[16]byte:
|
|
*d = col.col.Row(row)
|
|
case **[16]byte:
|
|
*d = new([16]byte)
|
|
**d = col.col.Row(row)
|
|
case sql.Scanner:
|
|
return d.Scan(col.row(row))
|
|
default:
|
|
return &ColumnConverterError{
|
|
Op: "ScanRow",
|
|
To: fmt.Sprintf("%T", dest),
|
|
From: "IPv6",
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func strToIPV6(strIp string) (netip.Addr, error) {
|
|
ip, err := netip.ParseAddr(strIp)
|
|
if err != nil {
|
|
return netip.Addr{}, err
|
|
}
|
|
return ip, nil
|
|
}
|
|
|
|
func (col *IPv6) AppendV6IPs(ips []netip.Addr) {
|
|
for i := range ips {
|
|
col.col.Append(proto.ToIPv6(ips[i]))
|
|
}
|
|
}
|
|
|
|
func (col *IPv6) Append(v any) (nulls []uint8, err error) {
|
|
switch v := v.(type) {
|
|
case []string:
|
|
nulls = make([]uint8, len(v))
|
|
ips := make([]netip.Addr, len(v), len(v))
|
|
for i := range v {
|
|
ip, err := strToIPV6(v[i])
|
|
if err != nil {
|
|
return nulls, &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
Hint: "invalid IP format",
|
|
}
|
|
}
|
|
ips[i] = ip
|
|
}
|
|
col.AppendV6IPs(ips)
|
|
case []*string:
|
|
nulls = make([]uint8, len(v))
|
|
ips := make([]netip.Addr, len(v), len(v))
|
|
for i := range v {
|
|
switch {
|
|
case v[i] != nil:
|
|
ip, err := strToIPV6(*v[i])
|
|
if err != nil {
|
|
return nulls, &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
Hint: "invalid IP format",
|
|
}
|
|
}
|
|
ips[i] = ip
|
|
default:
|
|
ips[i] = netip.Addr{}
|
|
nulls[i] = 1
|
|
}
|
|
}
|
|
col.AppendV6IPs(ips)
|
|
case []netip.Addr:
|
|
nulls = make([]uint8, len(v))
|
|
for _, v := range v {
|
|
col.col.Append(proto.ToIPv6(v))
|
|
}
|
|
case []*netip.Addr:
|
|
nulls = make([]uint8, len(v))
|
|
for i, v := range v {
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(*v))
|
|
default:
|
|
nulls[i] = 1
|
|
col.col.Append([16]byte{})
|
|
}
|
|
}
|
|
case []net.IP:
|
|
nulls = make([]uint8, len(v))
|
|
for _, v := range v {
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(v))))
|
|
}
|
|
case []*net.IP:
|
|
nulls = make([]uint8, len(v))
|
|
for i, v := range v {
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(*v))))
|
|
default:
|
|
nulls[i] = 1
|
|
col.col.Append([16]byte{})
|
|
}
|
|
}
|
|
case [][]byte:
|
|
nulls = make([]uint8, len(v))
|
|
for _, v := range v {
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(v))))
|
|
}
|
|
case []*[]byte:
|
|
nulls = make([]uint8, len(v))
|
|
for i, v := range v {
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(*v))))
|
|
default:
|
|
nulls[i] = 1
|
|
col.col.Append([16]byte{})
|
|
}
|
|
}
|
|
case [][16]byte:
|
|
for _, v := range v {
|
|
col.col.Append(v)
|
|
}
|
|
case []*[16]byte:
|
|
nulls = make([]uint8, len(v))
|
|
for i, v := range v {
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(*v)
|
|
default:
|
|
nulls[i] = 1
|
|
col.col.Append([16]byte{})
|
|
}
|
|
}
|
|
case []proto.IPv6:
|
|
for _, v := range v {
|
|
col.col.Append(v)
|
|
}
|
|
case []*proto.IPv6:
|
|
nulls = make([]uint8, len(v))
|
|
for i, v := range v {
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(*v)
|
|
default:
|
|
nulls[i] = 1
|
|
col.col.Append([16]byte{})
|
|
}
|
|
}
|
|
default:
|
|
if valuer, ok := v.(driver.Valuer); ok {
|
|
val, err := valuer.Value()
|
|
if err != nil {
|
|
return nil, &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
From: fmt.Sprintf("%T", v),
|
|
Hint: fmt.Sprintf("could not get driver.Valuer value, try using %s", col.Type()),
|
|
}
|
|
}
|
|
return col.Append(val)
|
|
}
|
|
return nil, &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
From: fmt.Sprintf("%T", v),
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (col *IPv6) AppendRow(v any) (err error) {
|
|
switch v := v.(type) {
|
|
case string:
|
|
ip, err := strToIPV6(v)
|
|
if err != nil {
|
|
return &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
Hint: "invalid IP format",
|
|
}
|
|
}
|
|
col.col.Append(ip.As16())
|
|
case *string:
|
|
switch {
|
|
case v != nil:
|
|
ip, err := strToIPV6(*v)
|
|
if err != nil {
|
|
return &ColumnConverterError{
|
|
Op: "Append",
|
|
To: "IPv6",
|
|
Hint: "invalid IP format",
|
|
}
|
|
}
|
|
col.col.Append(ip.As16())
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case netip.Addr:
|
|
col.col.Append(proto.ToIPv6(v))
|
|
case *netip.Addr:
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(*v))
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case net.IP:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(v))))
|
|
case *net.IP:
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(*v))))
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case []byte:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(v))))
|
|
case *[]byte:
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(proto.ToIPv6(netip.AddrFrom16(IPv6ToBytes(*v))))
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case [16]byte:
|
|
col.col.Append(v)
|
|
case *[16]byte:
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(*v)
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case proto.IPv6:
|
|
col.col.Append(v)
|
|
case *proto.IPv6:
|
|
switch {
|
|
case v != nil:
|
|
col.col.Append(*v)
|
|
default:
|
|
col.col.Append([16]byte{})
|
|
}
|
|
case nil:
|
|
col.col.Append([16]byte{})
|
|
default:
|
|
if valuer, ok := v.(driver.Valuer); ok {
|
|
val, err := valuer.Value()
|
|
if err != nil {
|
|
return &ColumnConverterError{
|
|
Op: "AppendRow",
|
|
To: "IPv6",
|
|
From: fmt.Sprintf("%T", v),
|
|
Hint: fmt.Sprintf("could not get driver.Valuer value, try using %s", col.Type()),
|
|
}
|
|
}
|
|
return col.AppendRow(val)
|
|
}
|
|
return &ColumnConverterError{
|
|
Op: "AppendRow",
|
|
To: "IPv6",
|
|
From: fmt.Sprintf("%T", v),
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (col *IPv6) Decode(reader *proto.Reader, rows int) error {
|
|
return col.col.DecodeColumn(reader, rows)
|
|
}
|
|
|
|
func (col *IPv6) Encode(buffer *proto.Buffer) {
|
|
col.col.EncodeColumn(buffer)
|
|
}
|
|
|
|
func IPv6ToBytes(ip net.IP) [16]byte {
|
|
if ip == nil {
|
|
return [16]byte{}
|
|
}
|
|
|
|
if len(ip) == 4 {
|
|
ip = ip.To16()
|
|
}
|
|
return [16]byte{ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]}
|
|
}
|
|
|
|
// TODO: This should probably return an netip.Addr
|
|
func (col *IPv6) row(i int) net.IP {
|
|
src := col.col.Row(i)
|
|
return src[:]
|
|
}
|
|
|
|
func (col *IPv6) rowAddr(i int) netip.Addr {
|
|
return col.col.Row(i).ToIP()
|
|
}
|
|
|
|
var _ Interface = (*IPv6)(nil)
|