Files
zeekay 0c90ebe02e debrand: finish the rename across source, docs and dev infra
Source: the unexported clickhouse struct becomes client, the ch receiver and
chproto import alias follow, error message prefixes read datastore, and the
JSON serializer interface drops the vendor infix. resources' metadata key and
its accessor are renamed together, with a test proving the embedded YAML still
unmarshals — a silent drift there would have made every connection take the
unsupported-server-version branch.

Codegen: all three templates still emitted the upstream module paths, so
regenerating would have quietly undone the rename. Note the templates have
drifted from the files they produce (regenerating today drops QBit and
scanTypeDuration), so the generated files are left as tracked and only the
templates are corrected.

Dead links: an earlier mechanical pass invented URLs that do not resolve —
github.com/ClickHouse/datastore-go, hanzo-ds/driver issue numbers that belong to
upstream, and mangled names of independent projects (mailru, uptrace, nikepan,
EpicStep). Third-party names are not ours to rewrite, so those directories are
removed rather than repaired, and provenance comments now point at real files.

Dev infra: compose runs our own server image at the tag production runs, since
the vendor's alpine tag does not exist in our registry. Cluster hostnames,
nginx upstreams and server configs are renamed as one set.

CHANGELOG.md is upstream's release history for versions this module never
released; rewriting it would fabricate a lineage, so it is dropped and the
upstream base recorded in README instead.

The two long-standing vet findings are fixed by keying the struct literals
rather than suppressed. LICENSE and contributors/list keep the vendor name on
purpose: one is the copyright notice Apache-2.0 requires, the other is real
people's names. CI now enforces build, vet, test, gofmt and a grep gate.
2026-07-26 11:46:39 -07:00

4.7 KiB

datastore-go — Agent Instructions

github.com/hanzo-ds/go is the official Go client for Datastore. It exposes two surfaces:

  • Native API (datastore.Open) — full-featured, direct driver.Conn interface.
  • Standard library (database/sql) — compatibility shim via datastore_std.go.

For build, test, and local setup instructions see CONTRIBUTING.md and README.md.


Interfaces at a Glance

All user-facing types are in lib/driver/driver.go.

Interface Obtained from Key responsibility
Conn datastore.Open() Query, batch, exec, ping
Rows Conn.Query() Iterate result set
Row Conn.QueryRow() Single-row result
Batch Conn.PrepareBatch() Bulk insert lifecycle

Conn is the only entry point. Do not add package-level globals or alternative constructors without a clear reason.


Go Idioms Enforced Here

Follow Go Code Review Comments in full. The rules below are the ones that matter most in this codebase.

Errors

  • Never discard errors with _. Return, handle, or wrap — never swallow.
  • Error strings: lowercase, no trailing punctuation — "datastore: connection closed".
  • Wrap with fmt.Errorf("context: %w", err) to preserve the chain; sentinel errors live in datastore.go.
  • Do not panic in library code. Panics belong only in init() for invariants that can never recover.
  • Error message returned to the end-user should be actionable as possible.

Context

  • Every network call takes context.Context as its first parameter — no exceptions.
  • Never store a Context in a struct field.
  • Deadlines and timeouts are the caller's responsibility, not the library's.

Interfaces

  • Define interfaces at the point of consumption, not implementation (lib/driver is consumed by both the root package and by users).
  • Do not introduce an interface solely to enable test mocking. Write integration tests against a real Datastore instance.
  • Prefer small, focused interfaces. If a new interface needs more than ~5 methods, reconsider the design.

Naming

  • Receiver names: short abbreviation of the type (c for conn, b for batch). Never self or this.
  • Acronyms keep their case: URL, HTTP, DSN, ID — not Url, Http, Dsn, Id.
  • Unexported constants: mixedCaps, never ALL_CAPS.
  • Avoid meaningless package names: util, common, helpers, misc.

Structs & ownership

  • batch holds a mutex — never copy it by value; always use a pointer.
  • Column implementations in lib/column/ use pointer receivers throughout; stay consistent.

Goroutines

  • Always document when a goroutine exits and how it is stopped.
  • Prefer synchronous APIs. Async variants (e.g., WithAsync) are opt-in through context, not the default path.

Imports

  • Three groups separated by blank lines: stdlib → external → internal (github.com/hanzo-ds/go).
  • Do not rename imports except to resolve collisions.

Design Principle

Make the API easy to use correctly and hard to use incorrectly.

Every API decision in this driver reflects this principle:

  • Batch.Send() marks the batch as sent; all subsequent calls return ErrBatchAlreadySent. You cannot accidentally double-send.
  • Rows must be explicitly closed. Leaving it open holds a connection. Stats() exposes pool pressure so leaks are visible.
  • Parameter binding (args ...any) prevents SQL injection. Never interpolate user input into query strings.
  • context.Context is required on every call — callers cannot accidentally fire a query without a cancellation path.
  • OpError carries the operation name and column name — callers get structured error information without string parsing.
  • Deprecated APIs (AsyncInsert) remain available alongside their replacements — callers are never broken silently.

When proposing a new API surface, ask: can a caller use this incorrectly without the compiler or runtime catching it? If yes, redesign.


Workflow

  • Do not commit directly to main. All changes go through a pull request.
  • Do not rebase or amend commits on a shared branch — add new commits instead.
  • Do not force-push to main.
  • Regression tests for bug fixes go in tests/issues/ named after the issue number: issue_1234_test.go.
  • New Datastore type support requires: a column implementation in lib/column/, a round-trip test in tests/, and an example in examples/datastore_api/.
  • When referencing Datastore SQL types, functions, or log messages in text, wrap them in backticks: `DateTime64`, `MergeTree`.