Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# ClickHouse [![run-tests](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml/badge.svg?branch=v2)](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/ClickHouse/clickhouse-go/v2.svg)](https://pkg.go.dev/github.com/ClickHouse/clickhouse-go/v2)
# ClickHouse [![run-tests](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml/badge.svg?branch=v2)](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/Altinity/clickhouse-go/v2.svg)](https://pkg.go.dev/github.com/Altinity/clickhouse-go/v2)

Golang SQL database client for [ClickHouse](https://clickhouse.com/).

## Install

```sh
go get github.com/ClickHouse/clickhouse-go/v2
go get github.com/Altinity/clickhouse-go/v2
```

## Which interface should I use?
Expand Down
2 changes: 1 addition & 1 deletion TYPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ import (
"fmt"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

func main() {
Expand Down
6 changes: 3 additions & 3 deletions benchmark/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"context"
"crypto/tls"
"encoding/json"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests"
"github.com/Altinity/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2/lib/driver"
clickhouse_tests "github.com/Altinity/clickhouse-go/v2/tests"
"os"
"testing"
)
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/read-native/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"context"
"fmt"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
"log"
"testing"
"time"
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/read-native/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

func benchmarkRead(conn clickhouse.Conn) error {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/read/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

_ "github.com/ClickHouse/clickhouse-go/v2"
_ "github.com/Altinity/clickhouse-go/v2"
)

func benchmarkRead(conn *sql.DB) error {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-async-std/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-async/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-compress-buffer-limit/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"context"
"fmt"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
"log"
"runtime"
"testing"
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-native-columnar/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-native-struct/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-native/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write-native/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"context"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/Altinity/clickhouse-go/v2"
"log"
"testing"
"time"
Expand Down
2 changes: 1 addition & 1 deletion benchmark/v2/write/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"time"

_ "github.com/ClickHouse/clickhouse-go/v2"
_ "github.com/Altinity/clickhouse-go/v2"
)

const ddl = `
Expand Down
4 changes: 2 additions & 2 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"strings"
"time"

"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/driver"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion chcol.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package clickhouse

import "github.com/ClickHouse/clickhouse-go/v2/lib/chcol"
import "github.com/Altinity/clickhouse-go/v2/lib/chcol"

// Re-export chcol types/funcs to top level clickhouse package

Expand Down
8 changes: 4 additions & 4 deletions clickhouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (

_ "time/tzdata"

"github.com/ClickHouse/clickhouse-go/v2/contributors"
"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/contributors"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/driver"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

type Conn = driver.Conn
Expand Down
21 changes: 20 additions & 1 deletion clickhouse_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"time"

"github.com/ClickHouse/ch-go/compress"
"github.com/ClickHouse/clickhouse-go/v2/lib/churl"
"github.com/Altinity/clickhouse-go/v2/lib/churl"
)

type CompressionMethod byte
Expand Down Expand Up @@ -67,6 +67,21 @@ type Auth struct { // has_control_character
Password string
}

// ClusterCredentials configures client-side interserver authentication.
// When Secret is non-empty, the client authenticates as a trusted cluster
// peer using the shared cluster secret instead of a user password, and the
// server executes queries as the InitialUser set on the connection's Auth
// or overridden per-query via WithInitialUser.
//
// See https://clickhouse.com/docs/operations/server-configuration-parameters/settings#remote_servers
// and the interserver secret protocol handled in `src/Server/TCPHandler.cpp`.
type ClusterCredentials struct {
// Name is the cluster name configured in ClickHouse remote_servers.
Name string
// Secret is the shared cluster secret. Empty disables interserver mode.
Secret string
}

type Compression struct {
Method CompressionMethod
// this only applies to lz4, lz4hc, zlib, and brotli compression algorithms
Expand Down Expand Up @@ -121,6 +136,10 @@ type Options struct {
TLS *tls.Config
Addr []string
Auth Auth
// Cluster enables interserver-secret authentication. When Cluster.Secret
// is set, Auth.Username/Password are ignored during the handshake and the
// client impersonates a trusted cluster peer. Queries run as InitialUser.
Cluster ClusterCredentials
DialContext func(ctx context.Context, addr string) (net.Conn, error)
DialStrategy func(ctx context.Context, connID int, options *Options, dial Dial) (DialResult, error)

Expand Down
2 changes: 1 addition & 1 deletion clickhouse_rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"database/sql"
"io"

"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

type rows struct {
Expand Down
4 changes: 2 additions & 2 deletions clickhouse_rows_column_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package clickhouse
import (
"reflect"

"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/driver"
)

type columnType struct {
Expand Down
4 changes: 2 additions & 2 deletions clickhouse_rows_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package clickhouse

import (
"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
"github.com/stretchr/testify/assert"
"strconv"
"testing"
Expand Down
4 changes: 2 additions & 2 deletions clickhouse_std.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"sync/atomic"
"syscall"

"github.com/ClickHouse/clickhouse-go/v2/lib/column"
chdriver "github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"github.com/Altinity/clickhouse-go/v2/lib/column"
chdriver "github.com/Altinity/clickhouse-go/v2/lib/driver"
)

var globalConnID int64
Expand Down
2 changes: 1 addition & 1 deletion client_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"sort"
"strings"

"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

const ClientName = "clickhouse-go"
Expand Down
21 changes: 18 additions & 3 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ import (
"crypto/tls"
"errors"
"fmt"
"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"io"
"log/slog"
"net"
"sync"
"syscall"
"time"

"github.com/ClickHouse/clickhouse-go/v2/resources"
"github.com/Altinity/clickhouse-go/v2/resources"

"github.com/ClickHouse/ch-go/compress"
chproto "github.com/ClickHouse/ch-go/proto"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

func dial(ctx context.Context, addr string, num int, opt *Options) (*connect, error) {
Expand Down Expand Up @@ -135,12 +135,27 @@ type connect struct {
maxCompressionBuffer int
readerMutex sync.Mutex
closeMutex sync.Mutex
// clusterSalt is the 32-byte salt sent during an interserver handshake
// and reused when signing every query on this connection. Empty when
// Options.Cluster.Secret is not configured.
clusterSalt string
}

func (c *connect) connID() int {
return c.id
}

// effectiveInitialUser returns the user to put on the outgoing
// `ClientInfo.initial_user` slot. The per-query override wins; otherwise we
// fall back to Auth.Username so interserver-mode connections execute as the
// configured default user when no per-query user is set.
func (c *connect) effectiveInitialUser(queryUser string) string {
if queryUser != "" {
return queryUser
}
return c.opt.Auth.Username
}

func (c *connect) getLogger() *slog.Logger {
return c.logger
}
Expand Down
2 changes: 1 addition & 1 deletion conn_async_insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package clickhouse
import (
"context"

"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

func (c *connect) asyncInsert(ctx context.Context, query string, wait bool, args ...any) error {
Expand Down
6 changes: 3 additions & 3 deletions conn_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"syscall"
"time"

"github.com/ClickHouse/clickhouse-go/v2/lib/column"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/column"
"github.com/Altinity/clickhouse-go/v2/lib/driver"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

var insertMatch = regexp.MustCompile(`(?i)(?:(?:--[^\n]*|#![^\n]*|#\s[^\n]*)\n\s*)*(INSERT\s+INTO\s+[^( ]+(?:\s*\([^()]*(?:\([^()]*\)[^()]*)*\))?)(?:\s*VALUES)?`)
Expand Down
2 changes: 1 addition & 1 deletion conn_error_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

"github.com/ClickHouse/ch-go/compress"
chproto "github.com/ClickHouse/ch-go/proto"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down
2 changes: 1 addition & 1 deletion conn_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package clickhouse

import (
"context"
"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
"time"
)

Expand Down
21 changes: 19 additions & 2 deletions conn_handshake.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package clickhouse

import (
"crypto/rand"
_ "embed"
"fmt"
"log/slog"
"time"

"github.com/ClickHouse/clickhouse-go/v2/lib/proto"
"github.com/Altinity/clickhouse-go/v2/lib/proto"
)

// interserverSaltLen matches the cap enforced by ClickHouse
// `TCPHandler::processClusterNameAndSalt` which calls
// `readStringBinary(salt, *in, 32)`.
const interserverSaltLen = 32

func (c *connect) handshake(auth Auth) error {
defer c.buffer.Reset()
c.logger.Debug("handshake: sending client hello",
Expand All @@ -28,7 +34,18 @@ func (c *connect) handshake(auth Auth) error {
ClientVersion: proto.Version{ClientVersionMajor, ClientVersionMinor, ClientVersionPatch}, //nolint:govet
}
handshake.Encode(c.buffer)
{
if c.opt.Cluster.Secret != "" {
salt := make([]byte, interserverSaltLen)
if _, err := rand.Read(salt); err != nil {
return fmt.Errorf("handshake: failed to generate interserver salt: %w", err)
}
c.clusterSalt = string(salt)
c.buffer.PutString(auth.Database)
c.buffer.PutString(proto.UserInterserverMarker)
c.buffer.PutString("")
c.buffer.PutString(c.opt.Cluster.Name)
c.buffer.PutString(c.clusterSalt)
} else {
c.buffer.PutString(auth.Database)
c.buffer.PutString(auth.Username)
c.buffer.PutString(auth.Password)
Expand Down
Loading