embeddedclickhouse

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

README

embedded-clickhouse

Go Reference Go Report Card codecov CI

Run a real ClickHouse database locally on Linux or macOS as part of another Go application or test.

When testing, this provides a much higher level of confidence than mocking or using Docker. It requires no external dependencies beyond the Go toolchain — no Docker, no testcontainers, no pre-installed ClickHouse.

Inspired by fergusstrange/embedded-postgres. ClickHouse binaries are fetched directly from official GitHub releases.

Why not testcontainers?

The story starts in a GitLab CI pipeline.

We had a Go service that talked to ClickHouse, and we wanted real integration tests — not mocks, not stubs, just actual SQL hitting an actual database. The natural choice was testcontainers-go. We added the dependency, wrote the tests, pushed — and immediately hit a wall.

testcontainers-go needs a Docker daemon. In GitLab CI that means picking your poison:

Docker-in-Docker (DinD) — spin up a docker:dind service alongside your job. It works, but the service container must run with privileged: true. GitLab's shared runners disable privileged mode by default, and many self-hosted runner fleets lock it down for good reason: a privileged DinD container has unrestricted access to the host kernel. One misconfigured job and you're escalated to root on the runner.

Docker-outside-of-Docker (DooD) — mount /var/run/docker.sock from the host into the job container. Sounds safer, but the Docker socket is a root-equivalent backdoor. Any code running in the job can create a privileged container that bind-mounts / from the host. Security teams tend to notice this and the mount disappears from the runner config shortly after.

On top of the privilege problem, testcontainers spins up a sidecar called Ryuk — a reaper container responsible for cleaning up after crashed tests. Ryuk needs to bind a port and phone home to the test process. In CI networks with strict firewall rules, Ryuk silently fails to connect, producing cryptic context deadline exceeded errors that vanish on retry and reappear at random. Debugging it means grepping through nested container logs while your CI queue backs up.

We tried Podman as a rootless alternative. Podman rootless requires disabling Ryuk entirely (TESTCONTAINERS_RYUK_DISABLED=true), which means manual cleanup. Rootful Podman needs ryuk.container.privileged=true, which brings the privilege problem back through a different door.

At some point the complexity of the setup exceeded the complexity of the thing we were testing.

The insight from fergusstrange/embedded-postgres was that you don't need Docker at all. ClickHouse ships as a single self-contained binary. You can download it, verify its checksum, and run it as a child process — no daemon, no socket, no sidecar, no privilege escalation. The binary starts in under a second, listens on a random port, and exits when your test exits.

embedded-clickhouse applies that same idea to ClickHouse. The binary is fetched once, cached in ~/.cache/embedded-clickhouse/, and reused across test runs. In CI, you cache that directory and the download never happens again. No Docker. No privileged runners. No Ryuk.

Installation

go get github.com/franchb/embedded-clickhouse

Requires Go 1.25+.

Quick start

func TestQuery(t *testing.T) {
    ch := embeddedclickhouse.NewServerForTest(t)
    // server starts automatically; t.Cleanup calls Stop()

    db, err := sql.Open("clickhouse", ch.DSN())
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()

    var result int
    db.QueryRow("SELECT 1").Scan(&result)
    // result == 1
}

How to use

Defaults
Configuration Default
Version V25_8 (25.8.16.34-lts)
TCP Port Auto-allocated
HTTP Port Auto-allocated
Cache Path $XDG_CACHE_HOME/embedded-clickhouse/ or ~/.cache/embedded-clickhouse/
Data Path Temporary directory (removed on Stop)
Start Timeout 30 seconds
Stop Timeout 10 seconds
Logger os.Stdout
Minimal usage
ch := embeddedclickhouse.NewServer()
if err := ch.Start(); err != nil {
    log.Fatal(err)
}
defer ch.Stop()

// ch.DSN()     => "clickhouse://127.0.0.1:<port>/default"
// ch.HTTPURL() => "http://127.0.0.1:<port>"
Custom configuration
ch := embeddedclickhouse.NewServer(
    embeddedclickhouse.DefaultConfig().
        Version(embeddedclickhouse.V25_3).
        TCPPort(19000).
        HTTPPort(18123).
        DataPath("/tmp/ch-data").
        StartTimeout(60 * time.Second).
        Logger(io.Discard).
        Settings(map[string]string{"max_threads": "2"}),
)
if err := ch.Start(); err != nil {
    log.Fatal(err)
}
defer ch.Stop()
TestMain pattern
var testServer *embeddedclickhouse.EmbeddedClickHouse

func TestMain(m *testing.M) {
    testServer = embeddedclickhouse.NewServer(
        embeddedclickhouse.DefaultConfig().
            Version(embeddedclickhouse.V25_8),
    )
    if err := testServer.Start(); err != nil {
        log.Fatal(err)
    }
    code := m.Run()
    testServer.Stop()
    os.Exit(code)
}

func TestSomething(t *testing.T) {
    db, err := sql.Open("clickhouse", testServer.DSN())
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()
    // ...
}
Per-test with auto-cleanup
func TestInsertAndSelect(t *testing.T) {
    ch := embeddedclickhouse.NewServerForTest(t)
    // Stop() is called via t.Cleanup

    db, err := sql.Open("clickhouse", ch.DSN())
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()

    db.Exec(`CREATE TABLE t (id UInt64) ENGINE = MergeTree() ORDER BY id`)
    db.Exec(`INSERT INTO t VALUES (1), (2), (3)`)

    var count int
    db.QueryRow("SELECT count() FROM t").Scan(&count)
    // count == 3
}

Cluster mode

Cluster mode runs multiple ClickHouse replicas on localhost using embedded Keeper (Raft-based coordination built into the ClickHouse binary). No additional binaries or Docker containers needed.

This enables testing ReplicatedMergeTree tables with ON CLUSTER queries — the same binary handles both the database engine and the coordination layer.

Quick start (cluster)
func TestReplication(t *testing.T) {
    cluster := embeddedclickhouse.NewClusterForTest(t, 3)
    // 3 nodes start automatically; t.Cleanup calls Stop()

    db, err := sql.Open("clickhouse", cluster.DSN())
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()

    db.Exec(`CREATE TABLE t ON CLUSTER 'test_cluster' (id UInt64)
        ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/t', '{replica}')
        ORDER BY id`)
    db.Exec(`INSERT INTO t VALUES (1), (2), (3)`)

    // Read from a different replica:
    db1, _ := sql.Open("clickhouse", cluster.Node(1).DSN())
    defer db1.Close()
    db1.Exec("SYSTEM SYNC REPLICA t")

    var count int
    db1.QueryRow("SELECT count() FROM t").Scan(&count)
    // count == 3
}
Manual Start/Stop (cluster)
cluster := embeddedclickhouse.NewCluster(3)
if err := cluster.Start(); err != nil {
    log.Fatal(err)
}
defer cluster.Stop()

cluster.DSN()           // DSN for node 0
cluster.Node(0).DSN()   // same as above
cluster.Node(1).DSN()   // DSN for node 1
cluster.ClusterName()   // "test_cluster"
Cluster defaults
Configuration Default
Replicas User-specified (min 2)
Start Timeout 120 seconds
Memory per node 1 GiB (max_server_memory_usage)
Cluster name test_cluster
All ports Auto-allocated

Each node requires 5 ports (TCP, HTTP, interserver HTTP, Keeper client, Keeper Raft), all auto-allocated on localhost. The 1 GiB per-node memory default prevents OOM on CI machines running 3 replicas. Override via Settings(map[string]string{"max_server_memory_usage": "2147483648"}).

Composability

embedded-clickhouse handles ClickHouse itself. For external dependencies (Kafka, S3, etc.), combine with testcontainers or docker-compose — ClickHouse connects to them via exposed ports.

Configuration reference

All configuration methods use a builder pattern with value receivers, so the original config is never mutated:

base := embeddedclickhouse.DefaultConfig()
custom := base.Version(embeddedclickhouse.V25_3) // base is unchanged
Method Description
Version(ClickHouseVersion) ClickHouse version to download and run
TCPPort(uint32) Native protocol port (0 = auto-allocate)
HTTPPort(uint32) HTTP interface port (0 = auto-allocate)
CachePath(string) Override binary cache directory
DataPath(string) Persistent data directory (survives Stop)
BinaryPath(string) Use a pre-existing binary, skip download
BinaryRepositoryURL(string) Custom mirror URL (default: GitHub releases)
StartTimeout(time.Duration) Max wait for server readiness
StopTimeout(time.Duration) Max wait for graceful shutdown
Logger(io.Writer) Destination for server stdout/stderr
Settings(map[string]string) Arbitrary ClickHouse server settings

Available versions

Constant Version Channel
V26_1 26.1.3.52-stable Stable
V25_8 25.8.16.34-lts LTS (default)
V25_3 25.3.14.14-lts LTS

Any version string can be used — these constants are provided for convenience. Pass the full version from a ClickHouse release tag, e.g. embeddedclickhouse.ClickHouseVersion("24.8.6.70-lts").

Server accessors

After Start() returns successfully:

Method Example return value
TCPAddr() "127.0.0.1:19000"
HTTPAddr() "127.0.0.1:18123"
DSN() "clickhouse://127.0.0.1:19000/default"
HTTPURL() "http://127.0.0.1:18123"

Platform support

OS Arch Asset type
Linux amd64 .tgz archive
Linux arm64 .tgz archive
macOS amd64 Raw binary
macOS arm64 Raw binary

CI caching

The downloaded ClickHouse binary (~200MB for Linux, ~130MB for macOS) is cached at the cache path. In CI, cache this directory to avoid re-downloading on every run:

# GitHub Actions
- uses: actions/cache@v4
  with:
    path: ~/.cache/embedded-clickhouse
    key: clickhouse-${{ runner.os }}-${{ runner.arch }}-25.8.16.34-lts

Memory limits

No server memory limit is imposed by default. ClickHouse uses its built-in ratio-based default (max_server_memory_usage_to_ram_ratio = 0.9), which caps the server at 90% of available RAM.

ClickHouse has two separate memory settings:

  • max_server_memory_usage — server-wide ceiling across all queries and background operations
  • max_memory_usage — per-query limit (set in user profiles, not server config)

For constrained CI environments, set an explicit server limit via Settings():

embeddedclickhouse.DefaultConfig().
    Settings(map[string]string{"max_server_memory_usage": "1073741824"}) // 1 GiB

Environments with less than 2 GB total RAM will be fragile regardless of settings — ClickHouse needs memory for internal overhead (mark cache, logs, query cache, metadata) beyond query execution.

How it works

  1. Download — fetches the ClickHouse binary from GitHub releases (or a configured mirror) on first use
  2. Verify — checks SHA512 hash for downloaded assets
  3. Cache — stores the extracted binary at ~/.cache/embedded-clickhouse/ for reuse
  4. Configure — generates a minimal XML config with allocated ports and a temp data directory
  5. Start — launches clickhouse server as a child process
  6. Health check — polls GET /ping every 100ms until the server responds
  7. Stop — sends SIGTERM, waits for graceful shutdown, then SIGKILL if needed; cleans up the temp directory

License

Apache 2.0

Documentation

Overview

Package embeddedclickhouse provides an embedded ClickHouse server for Go tests. It downloads, caches, and manages a real ClickHouse server process, similar to how fergusstrange/embedded-postgres works for PostgreSQL.

Index

Examples

Constants

View Source
const DefaultVersion = V25_8

DefaultVersion is the default ClickHouse version used when none is specified.

Variables

View Source
var ErrBinaryNotFound = errors.New("embedded-clickhouse: binary not found in archive")

ErrBinaryNotFound is returned when the ClickHouse binary cannot be located inside a downloaded archive.

View Source
var ErrClusterAlreadyStarted = errors.New("embedded-clickhouse: cluster is already started")

ErrClusterAlreadyStarted is returned by Start when the cluster is already running.

View Source
var ErrClusterManaged = errors.New("embedded-clickhouse: node is managed by a cluster; use Cluster.Start/Stop")

ErrClusterManaged is returned when Start or Stop is called on a node owned by a Cluster.

View Source
var ErrClusterNotStarted = errors.New("embedded-clickhouse: cluster has not been started")

ErrClusterNotStarted is returned when accessing cluster resources before Start.

View Source
var ErrDownloadFailed = errors.New("embedded-clickhouse: download failed")

ErrDownloadFailed is returned when the HTTP download of a ClickHouse asset returns a non-200 status.

View Source
var ErrInvalidPath = errors.New("embedded-clickhouse: invalid destination path")

ErrInvalidPath is returned when a destination path contains a path traversal sequence ("..").

View Source
var ErrInvalidReplicaCount = errors.New("embedded-clickhouse: replica count must be at least 2")

ErrInvalidReplicaCount is returned when the replica count is less than 2.

View Source
var ErrInvalidSettingKey = errors.New("embedded-clickhouse: invalid setting key")

ErrInvalidSettingKey is returned when a settings key contains characters that are unsafe in an XML element name.

View Source
var ErrKeeperNotReady = errors.New("embedded-clickhouse: keeper quorum not ready")

ErrKeeperNotReady is returned when the embedded Keeper quorum is not established within the timeout.

View Source
var ErrNodeOutOfRange = errors.New("embedded-clickhouse: node index out of range")

ErrNodeOutOfRange is returned when Node() is called with an index outside [0, replicas).

View Source
var ErrSHA512Mismatch = errors.New("embedded-clickhouse: SHA512 mismatch")

ErrSHA512Mismatch is returned when the downloaded file's SHA512 hash does not match the expected value.

View Source
var ErrSHA512NotFound = errors.New("embedded-clickhouse: SHA512 hash not found")

ErrSHA512NotFound is returned when the SHA512 checksum file does not contain a hash for the expected filename.

View Source
var ErrServerAlreadyStarted = errors.New("embedded-clickhouse: server is already started")

ErrServerAlreadyStarted is returned by Start when the server is already running.

View Source
var ErrServerNotStarted = errors.New("embedded-clickhouse: server has not been started")

ErrServerNotStarted is returned by Stop when the server has not been started.

View Source
var ErrStopTimeout = errors.New("embedded-clickhouse: server did not stop within timeout, killed")

ErrStopTimeout is returned when the server does not stop within the configured StopTimeout; the process is killed.

View Source
var ErrUnexpectedAddrType = errors.New("embedded-clickhouse: unexpected listener address type")

ErrUnexpectedAddrType is returned when the listener address is not the expected *net.TCPAddr type.

View Source
var ErrUnknownAssetType = errors.New("embedded-clickhouse: unknown asset type")

ErrUnknownAssetType is returned when an unrecognised platform asset type is encountered.

View Source
var ErrUnsupportedPlatform = errors.New("embedded-clickhouse: unsupported platform")

ErrUnsupportedPlatform is returned when the current OS/architecture has no ClickHouse release asset.

Functions

This section is empty.

Types

type ClickHouseVersion

type ClickHouseVersion string

ClickHouseVersion represents a ClickHouse server version string.

const V25_3 ClickHouseVersion = "25.3.14.14-lts"

V25_3 is ClickHouse 25.3 (LTS channel).

const V25_8 ClickHouseVersion = "25.8.16.34-lts"

V25_8 is ClickHouse 25.8 (LTS channel).

const V26_1 ClickHouseVersion = "26.1.3.52-stable"

V26_1 is ClickHouse 26.1 (stable channel).

type Cluster added in v0.3.0

type Cluster struct {
	// contains filtered or unexported fields
}

Cluster manages a multi-replica ClickHouse cluster using embedded Keeper for coordination. All replicas run on localhost with auto-allocated ports. The cluster presents a single shard with N replicas, suitable for testing ReplicatedMergeTree tables with ON CLUSTER queries.

Example (ReplicatedTable)

ExampleCluster_replicatedTable demonstrates a full ReplicatedMergeTree workflow: create a table ON CLUSTER, insert on one node, sync and read from another.

package main

import (
	"database/sql"
	"fmt"
	"io"
	"testing"

	_ "github.com/ClickHouse/clickhouse-go/v2"
	embeddedclickhouse "github.com/franchb/embedded-clickhouse"
)

func main() {
	if testing.Short() {
		fmt.Println(2)
		return
	}

	cluster := embeddedclickhouse.NewCluster(2, embeddedclickhouse.DefaultConfig().Logger(io.Discard))
	if err := cluster.Start(); err != nil {
		panic(err)
	}
	defer cluster.Stop()

	db0, err := sql.Open("clickhouse", cluster.Node(0).DSN())
	if err != nil {
		panic(err)
	}
	defer db0.Close()

	db1, err := sql.Open("clickhouse", cluster.Node(1).DSN())
	if err != nil {
		panic(err)
	}
	defer db1.Close()

	// Create a replicated table on all nodes.
	_, err = db0.Exec(`
		CREATE TABLE example_repl ON CLUSTER 'test_cluster' (
			id UInt64,
			name String
		) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/example_repl', '{replica}')
		ORDER BY id
	`)
	if err != nil {
		panic(err)
	}

	// Insert on node 0.
	_, err = db0.Exec("INSERT INTO example_repl (id, name) VALUES (1, 'alice'), (2, 'bob')")
	if err != nil {
		panic(err)
	}

	// Sync and read from node 1.
	_, err = db1.Exec("SYSTEM SYNC REPLICA example_repl")
	if err != nil {
		panic(err)
	}

	var count int
	if err := db1.QueryRow("SELECT count() FROM example_repl").Scan(&count); err != nil {
		panic(err)
	}

	fmt.Println(count)
}
Output:

2

func NewCluster added in v0.3.0

func NewCluster(replicas int, config ...Config) *Cluster

NewCluster creates a new Cluster with the given number of replicas. If no config is provided, DefaultConfig() is used with a 120s start timeout.

Example

ExampleNewCluster demonstrates starting a 3-node ClickHouse cluster for replication testing.

package main

import (
	"io"
	"testing"

	_ "github.com/ClickHouse/clickhouse-go/v2"
	embeddedclickhouse "github.com/franchb/embedded-clickhouse"
)

func main() {
	if testing.Short() {
		return
	}

	cluster := embeddedclickhouse.NewCluster(3, embeddedclickhouse.DefaultConfig().Logger(io.Discard))
	if err := cluster.Start(); err != nil {
		panic(err)
	}
	defer cluster.Stop()

	// cluster.DSN()          => DSN for node 0
	// cluster.Node(0).DSN()  => same as above
	// cluster.Node(1).DSN()  => DSN for node 1
	// cluster.ClusterName()  => "test_cluster"
	//
	// Use ON CLUSTER queries with ReplicatedMergeTree:
	//   CREATE TABLE t ON CLUSTER 'test_cluster' (id UInt64)
	//     ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/t', '{replica}')
	//     ORDER BY id

}

func NewClusterForTest added in v0.3.0

func NewClusterForTest(tb testing.TB, replicas int, config ...Config) *Cluster

NewClusterForTest creates a cluster, starts it, and registers tb.Cleanup(cluster.Stop). Calls tb.Fatal on Start() error.

Example

ExampleNewClusterForTest demonstrates the per-test cluster helper pattern.

package main

import (
	"testing"

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

func main() {
	if testing.Short() {
		return
	}

	// In a real test, pass *testing.T here. The cluster starts automatically
	// and t.Cleanup registers Stop() for teardown.
	//
	// cluster := embeddedclickhouse.NewClusterForTest(t, 3)
	// db, _ := sql.Open("clickhouse", cluster.DSN())

}

func (*Cluster) ClusterName added in v0.3.0

func (c *Cluster) ClusterName() string

ClusterName returns the cluster name used in ON CLUSTER queries.

func (*Cluster) DSN added in v0.3.0

func (c *Cluster) DSN() string

DSN returns the DSN for the first node (shortcut for Node(0).DSN()).

func (*Cluster) Node added in v0.3.0

func (c *Cluster) Node(index int) *EmbeddedClickHouse

Node returns the i-th node (0-indexed). Panics if the cluster is not started or index is out of range.

func (*Cluster) Nodes added in v0.3.0

func (c *Cluster) Nodes() []*EmbeddedClickHouse

Nodes returns all cluster nodes. Returns nil if the cluster is not started.

func (*Cluster) Start added in v0.3.0

func (c *Cluster) Start() error

Start launches all cluster nodes and waits for Keeper quorum.

func (*Cluster) Stop added in v0.3.0

func (c *Cluster) Stop() error

Stop gracefully shuts down all cluster nodes in reverse order.

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config holds configuration for an embedded ClickHouse server.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with sensible defaults.

func (Config) BinaryPath

func (c Config) BinaryPath(path string) Config

BinaryPath uses a pre-existing ClickHouse binary, skipping download.

func (Config) BinaryRepositoryURL

func (c Config) BinaryRepositoryURL(url string) Config

BinaryRepositoryURL sets a custom mirror URL for downloading ClickHouse binaries.

func (Config) CachePath

func (c Config) CachePath(path string) Config

CachePath overrides the directory used to cache downloaded binaries.

func (Config) DataPath

func (c Config) DataPath(path string) Config

DataPath sets a persistent data directory that survives Stop.

func (Config) HTTPPort

func (c Config) HTTPPort(port uint32) Config

HTTPPort sets the HTTP port for the ClickHouse HTTP interface. 0 means auto-allocate (default).

func (Config) Logger

func (c Config) Logger(w io.Writer) Config

Logger sets the writer for server stdout/stderr output.

func (Config) Settings

func (c Config) Settings(s map[string]string) Config

Settings sets arbitrary ClickHouse server settings. The provided map is copied; subsequent caller mutations do not affect the Config.

Example

ExampleConfig_Settings demonstrates builder chaining and Settings usage.

package main

import (
	"io"
	"time"

	embeddedclickhouse "github.com/franchb/embedded-clickhouse"
)

func main() {
	cfg := embeddedclickhouse.DefaultConfig().
		Version(embeddedclickhouse.V25_3).
		TCPPort(19000).
		HTTPPort(18123).
		StartTimeout(60 * time.Second).
		Logger(io.Discard).
		Settings(map[string]string{
			"max_threads":             "2",
			"max_server_memory_usage": "2147483648", // 2 GiB
		})

	_ = cfg
}

func (Config) StartTimeout

func (c Config) StartTimeout(d time.Duration) Config

StartTimeout sets the maximum time to wait for the server to become ready.

func (Config) StopTimeout

func (c Config) StopTimeout(d time.Duration) Config

StopTimeout sets the maximum time to wait for the server to shut down gracefully.

func (Config) TCPPort

func (c Config) TCPPort(port uint32) Config

TCPPort sets the TCP port for the ClickHouse native protocol. 0 means auto-allocate (default).

func (Config) Version

func (c Config) Version(v ClickHouseVersion) Config

Version sets the ClickHouse version to use.

type EmbeddedClickHouse

type EmbeddedClickHouse struct {
	// contains filtered or unexported fields
}

EmbeddedClickHouse manages a ClickHouse server process for testing.

func NewServer

func NewServer(config ...Config) *EmbeddedClickHouse

NewServer creates a new EmbeddedClickHouse with the given config. If no config is provided, DefaultConfig() is used.

Example

ExampleNewServer demonstrates the minimal Start/Stop usage pattern.

package main

import (
	"io"
	"testing"

	embeddedclickhouse "github.com/franchb/embedded-clickhouse"
)

func main() {
	if testing.Short() {
		return
	}

	ch := embeddedclickhouse.NewServer(embeddedclickhouse.DefaultConfig().Logger(io.Discard))
	if err := ch.Start(); err != nil {
		panic(err)
	}
	defer ch.Stop()

	// ch.DSN()     => "clickhouse://127.0.0.1:<port>/default"
	// ch.HTTPURL() => "http://127.0.0.1:<port>"

}

func NewServerForTest

func NewServerForTest(tb testing.TB, config ...Config) *EmbeddedClickHouse

NewServerForTest creates a server, starts it, and registers t.Cleanup(server.Stop). Calls t.Fatal on Start() error.

Example

ExampleNewServerForTest demonstrates the per-test helper pattern.

package main

import (
	"testing"
)

func main() {
	if testing.Short() {
		return
	}

	// In a real test, pass *testing.T here. The server starts automatically
	// and t.Cleanup registers Stop() for teardown.
	//
	// ch := embeddedclickhouse.NewServerForTest(t)
	// db, _ := sql.Open("clickhouse", ch.DSN())

}

func (*EmbeddedClickHouse) DSN

func (e *EmbeddedClickHouse) DSN() string

DSN returns a ClickHouse DSN for use with clickhouse-go (e.g., "clickhouse://127.0.0.1:19000/default").

Example

ExampleEmbeddedClickHouse_DSN documents the DSN accessor.

package main

import (
	"io"
	"testing"

	embeddedclickhouse "github.com/franchb/embedded-clickhouse"
)

func main() {
	if testing.Short() {
		return
	}

	ch := embeddedclickhouse.NewServer(embeddedclickhouse.DefaultConfig().Logger(io.Discard))
	if err := ch.Start(); err != nil {
		panic(err)
	}
	defer ch.Stop()

	dsn := ch.DSN()
	_ = dsn // "clickhouse://127.0.0.1:<port>/default"
}

func (*EmbeddedClickHouse) HTTPAddr

func (e *EmbeddedClickHouse) HTTPAddr() string

HTTPAddr returns the HTTP address for the ClickHouse HTTP interface (e.g., "127.0.0.1:18123").

func (*EmbeddedClickHouse) HTTPURL

func (e *EmbeddedClickHouse) HTTPURL() string

HTTPURL returns the base HTTP URL (e.g., "http://127.0.0.1:18123").

func (*EmbeddedClickHouse) Start

func (e *EmbeddedClickHouse) Start() error

Start downloads the ClickHouse binary (if needed), generates config, and starts the server.

func (*EmbeddedClickHouse) Stop

func (e *EmbeddedClickHouse) Stop() error

Stop gracefully shuts down the ClickHouse server and cleans up resources.

func (*EmbeddedClickHouse) TCPAddr

func (e *EmbeddedClickHouse) TCPAddr() string

TCPAddr returns the TCP address for the ClickHouse native protocol (e.g., "127.0.0.1:19000").

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL