Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 40 additions & 17 deletions docs/reference/bindings-v1.md

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions docs/reference/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ go build -tags chtypes_linked ./... # + chtypes.OpenLinked (needs the artifact

Row and batch verdicts are **never** Go errors: they are `Outcome` in the result. Go errors are for the call as a whole, and each is a peer type, so a decline can never satisfy `errors.As` against the refusal type ([`bindings-v1.md` §4](bindings-v1.md#4-errors)).

| type | class |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `*SchemaError` | `CHS_REJECTED`: ClickHouse refused. `ChCode` is a real ClickHouse code, `ChName` its name in this build |
| `*UnsupportedError` | `CHS_DECLINED`: this build declines. Fall back to the server; never report it as a rejection |
| `*UsageError` | `CHS_INVALID_ARGUMENT`: misuse, such as a closed object, a refused spelling or a conflicting `Setup` |
| `*InternalError` | `CHS_INTERNAL`, or a document that does not decode |
| `*ArtifactError` | a fetch or load failure, with a `Code` (one of ten) and a sentinel per code for `errors.Is`, such as `ErrArtifactMissing` |
| type | class |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `*SchemaError` | `CHS_REJECTED`: ClickHouse refused. `ChCode` is a real ClickHouse code, `ChName` its name in this build |
| `*UnsupportedError` | `CHS_DECLINED`: this build declines. Fall back to the server; never report it as a rejection |
| `*UsageError` | `CHS_INVALID_ARGUMENT`: misuse, such as a closed object, a refused spelling or a conflicting `Setup` |
| `*InternalError` | `CHS_INTERNAL`, or a document that does not decode |
| `*ArtifactError` | a fetch or load failure, with a `Code` (an `ErrorCode`, one of the generated `Code…` constants) and a sentinel per code for `errors.Is`, such as `ErrArtifactMissing` |

All four call types embed `CallError`, whose five fields (`Status`, `ChCode`, `ChName`, `Message`, `Column`) read directly; `AsCallError` reads them from any of the four. `Message` and `Column` are byte strings, and `Error()` is the one lossy display form.

Expand Down Expand Up @@ -58,7 +58,7 @@ A string or byte-string input is a Go `string`, and a body is `[]byte`. A `Value

## The exit status of a failure

The library carries no exit status. `ErrorCode.ExitCode()` is a method of the shared code vocabulary, generated from `spec/fetch-v1/constants.json` (the table is [`fetch-v1.md` §8](../guides/fetch-v1.md#8-errors)), and the command below is the only caller that turns an error into a process status.
The library carries no exit status. `ErrorCode` and its `Code…` constants are generated from `spec/fetch-v1/constants.json`, with no method; a code's exit status is the table of [`fetch-v1.md` §8](../guides/fetch-v1.md#8-errors), and the command below is the only caller that turns an error into a process status. An `*ArtifactError`'s `Error()` names the request, the platform and the source a fetch error concerns, and `errors.Unwrap` reaches its cause.

## The command

Expand Down
22 changes: 11 additions & 11 deletions docs/reference/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ A bad **row** is a verdict, returned and never raised: a rejected row is a `RowR

## Setup, registry and opening

| Symbol | What it is |
| ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setup(*, timezone=None, defaults=None)` | The image zone and the default settings, chosen once, before the first open. A second call with the same arguments is a no-op; a different one is a `UsageError` naming both ([§6](bindings-v1.md)) |
| `Registry(*, fetch=None, autofetch=None, preload=())` | Opens nothing at construction. `autofetch` defaults to `CHTYPES_AUTOFETCH`, and is off when that is unset. `preload` opens each listed request at construction and never fetches |
| `Registry.for_version(request)` | `Library`. `request` is `26.8`, `26.8.15` or `26.8.15.10`: no `v` prefix, no channel suffix (a refused spelling is a `UsageError`). A request opened before returns the same `Library` |
| `Registry.installed()`, `Registry.libraries()` | The fetch layer's list of installed builds, as a tuple of `Resolved`; and the libraries this registry has opened, in order |
| `cache_root(options=None)`, `search_dirs(options=None)` | The resolved cache root (a `Path`), and the ordered directories searched (the root, then each system directory, as a tuple of `Path`): the fetch layer's own resolution, read-only, creating nothing |
| `FetchOptions(bases, cache_dir, system_dirs, token, trusted_keys, allow_unsigned, offline, frozen, lock_path, lock_write, update)` | A frozen dataclass of everything the fetch layer configures. A field left at its default falls back to the fetch layer's own defaults and environment |
| `Resolved`, `TrustedKey` | The fetch layer's record of an installed build (`Library.resolved` is the one that first opened an image), and a trusted ed25519 key |
| `open_unverified(path, *, allow=False)` | A local, unpublished build for the artifact producer's own suites. It needs `allow=True` and `CHTYPES_ALLOW_UNVERIFIED_LIBRARY=1`, and its `Library` has no `resolved` |
| Symbol | What it is |
| ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setup(*, timezone=None, defaults=None)` | The image zone and the default settings, chosen once, before the first open. A second call with the same arguments is a no-op; a different one is a `UsageError` naming both ([§6](bindings-v1.md)) |
| `Registry(*, fetch=None, autofetch=None, preload=())` | Opens nothing at construction. `autofetch` defaults to `CHTYPES_AUTOFETCH`, and is off when that is unset. `preload` opens each listed request at construction and never fetches |
| `Registry.for_version(request)` | `Library`. `request` is `26.8`, `26.8.15` or `26.8.15.10`: no `v` prefix, no channel suffix (a refused spelling is a `UsageError`). A request opened before returns the same `Library` |
| `Registry.installed()`, `Registry.libraries()` | The fetch layer's list of installed builds, as a tuple of `Resolved`; and the libraries this registry has opened, in order |
| `cache_root(options=None)`, `search_dirs(options=None)` | The resolved cache root (a `Path`), and the ordered directories searched (the root, then each system directory, as a tuple of `Path`): the fetch layer's own resolution, read-only, creating nothing |
| `FetchOptions(bases, cache_dir, system_dirs, token, trusted_keys, allow_unsigned, offline, frozen, lock_path, lock_write, update)` | A frozen dataclass of everything the fetch layer configures. A field left at its default falls back to the fetch layer's own defaults and environment. `trusted_keys` is raw ed25519 public keys as 64 hex digits each, the `CHTYPES_TRUSTED_KEYS` spelling |
| `Resolved` | The fetch layer's record of an installed build (`Library.resolved` is the one that first opened an image) |
| `open_unverified(path, *, allow=False)` | A local, unpublished build for the artifact producer's own suites. It needs `allow=True` and `CHTYPES_ALLOW_UNVERIFIED_LIBRARY=1`, and its `Library` has no `resolved` |

A library is never unloaded and never closed: there is no `Registry.close` or `Library.close`, and a loaded image lives until the process exits. Two registries, two spellings or a hardlink of one artifact share one image.

Expand Down Expand Up @@ -73,7 +73,7 @@ One table ([§4](bindings-v1.md)). The four call errors are peers under `CallErr
| `InternalError` | a library bug, or a document that does not decode |
| `ArtifactError` and one subclass per code | the loader's refusals and the fetch layer's errors, each with `.code`: `ArtifactMissingError`, `ArtifactUntrustedError`, `ArtifactCorruptError`, `ArtifactPinnedError`, `ArtifactUnpublishedError`, `ArtifactIncompatibleError`, `SourceUnreachableError`, `SourceUnauthorizedError`, `SourceForbiddenError`, `SourceIncompatibleError`, `CacheUnusableError`, `SourceRetiredError` |

`UnsupportedError` is a peer of `SchemaError`, not a subclass: `except SchemaError` never catches a decline. The `CODE_*` constants are the codes; `chtypes.ChtypesError` is the root of everything this package raises.
`UnsupportedError` is a peer of `SchemaError`, not a subclass: `except SchemaError` never catches a decline. The `CODE_*` constants are the codes, generated from `spec/fetch-v1/constants.json`, and each artifact class's `code` is one of them; `chtypes.ChtypesError` is the root of everything this package raises.

## The command

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Unix only: the loader is `dlopen`. Minimum supported Rust version 1.87. `cargo d

**Four call classes, peers of each other.** `Error::Schema` (ClickHouse itself would refuse), `Error::Unsupported` (this build declines; a server might accept), `Error::Usage` (misuse) and `Error::Internal` (a library bug) each carry a `CallError`: `status`, `ch_code`, `ch_name`, `message` and `column`, verbatim from the library. A decline is neither an acceptance nor a rejection: fall back to the server. `Error::call_error()` reads the five fields from any of the four.

**One family with the artifact errors.** `Error::ArtifactIncompatible` and `Error::ArtifactCorrupt` carry a `Refusal` (`reason`, `path`, `want`, `got`); the fetch layer's codes are one variant each (`ArtifactMissing`, `ArtifactUntrusted`, `ArtifactPinned`, `ArtifactUnpublished`, `SourceUnreachable`, `SourceUnauthorized`, `SourceForbidden`, `SourceIncompatible`, `CacheUnusable`, `SourceRetired`), and `Error::code()` names the `CHTYPES_*` code.
**One family with the artifact errors.** `Error::ArtifactIncompatible` and `Error::ArtifactCorrupt` carry a `Refusal` (`reason`, `path`, `want`, `got`: a one-sided refusal's finding is in `got`, and the fetch layer's own corruption has an empty `reason`); the fetch layer's codes are one variant each (`ArtifactMissing`, `ArtifactUntrusted`, `ArtifactPinned`, `ArtifactUnpublished`, `SourceUnreachable`, `SourceUnauthorized`, `SourceForbidden`, `SourceIncompatible`, `CacheUnusable`, `SourceRetired`), and `Error::code()` names the `CHTYPES_*` code, one of the `chtypes::code` constants generated from `spec/fetch-v1/constants.json`.

**Bytes are bytes.** A column name, a statement, a message and a rendered value come back as `RawText`: `as_bytes()` is authoritative, `as_str()` is `None` for bytes that are not UTF-8, and `Display` is the one lossy form. Inputs are `impl AsRef<[u8]>`, so `&str`, `&[u8]` and `Vec<u8>` all work. An export is a `Vec<u8>`.

Expand All @@ -34,7 +34,7 @@ Unix only: the loader is `dlopen`. Minimum supported Rust version 1.87. `cargo d

## The fetch options

`RegistryOptions::fetch` is a `FetchOptions` carrying everything [`fetch-v1.md`](../guides/fetch-v1.md) configures, each field defaulting to the fetch layer's own default (the environment, then the built-in value): `platform`, `bases`, `cache_dir`, `system_dirs`, `offline`, `frozen`, `lock_path`, `lock_write`, `update`, `allow_unsigned`, `trusted_keys` and `token`.
`RegistryOptions::fetch` is a `FetchOptions` carrying everything [`fetch-v1.md`](../guides/fetch-v1.md) configures, each field defaulting to the fetch layer's own default (the environment, then the built-in value): `bases`, `cache_dir`, `system_dirs`, `offline`, `frozen`, `lock_path`, `lock_write`, `update`, `allow_unsigned`, `trusted_keys` and `token`. No field names a platform: a registry opens libraries for this host, and `chtypes fetch --platform` names another.

`trusted_keys: Option<Vec<String>>` is the trust list: raw 32-byte ed25519 public keys, each as 64 hex digits. A non-empty list REPLACES the default trust (the release key); `None` reads `CHTYPES_TRUSTED_KEYS` (comma-separated), and the release key is used when neither names a key. A list never appends to the default, so trusting the SDK's fixture key means naming it (and the release key too, if both should verify). A key that is not 64 hex digits is `Error::Usage`.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A bad **row** is never an exception: the verdict is `RowResult#outcome`, one of
- `UsageError`: caller misuse, whichever side caught it (a closed object, a refused version spelling, a zone given twice).
- `InternalError`: a library bug, or a document that does not decode.

The four are **peers** under the abstract `CallError`: a decline never satisfies `instanceof SchemaError`. Loader and fetch errors are `ArtifactError`s (`ArtifactIncompatibleError`, `ArtifactCorruptError`, `ArtifactMissingError` and the rest of the fetch family); `ArtifactError` extends `ChtypesError`, as the other bindings' hierarchies have it, so catching `ChtypesError` takes the fetch and loader errors along with the call errors, and `isChtypesError` is true for every error this package throws on purpose.
The four are **peers** under the abstract `CallError`: a decline never satisfies `instanceof SchemaError`. Loader and fetch errors are `ArtifactError`s (`ArtifactIncompatibleError`, `ArtifactCorruptError`, `ArtifactMissingError` and the rest of the fetch family); `ArtifactError` extends `ChtypesError`, as the other bindings' hierarchies have it, so catching `ChtypesError` (`e instanceof ChtypesError`) takes the fetch and loader errors along with the call errors. `ArtifactError` carries `code` (an `ErrorCode`, one of the generated `CODE_*` constants) and a loader refusal's `reason`, `path`, `want` and `got`, which a fetch error leaves `undefined`.

## Setup, registry and library

Expand Down
2 changes: 1 addition & 1 deletion examples/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ func describeError(err error, what string) {
kv(" message", truncate(ie.Message, 84))
case errors.As(err, &ae):
kv(what, "*ArtifactError .Code="+string(ae.Code))
kv(" message", truncate(ae.Msg, 84))
kv(" message", truncate(ae.Error(), 84))
kv(" errors.Is(ErrArtifactMissing)", fmt.Sprintf("%v <- one sentinel per code", errors.Is(err, chtypes.ErrArtifactMissing)))
default:
kv(what, fmt.Sprintf("%T: %v", err, err))
Expand Down
6 changes: 3 additions & 3 deletions examples/ts/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ import {
ArtifactMissingError,
type BatchResult,
CallError,
ChtypesError,
DefaultKind,
DocFlags,
type FilterResult,
Format,
formatChName,
InternalError,
isChtypesError,
type Library,
Registry,
type RowResult,
Expand Down Expand Up @@ -731,7 +731,7 @@ function section10(lib: Library): void {
kv('four peers', 'SchemaError, UnsupportedError, UsageError, InternalError');
kv('common base', `CallError: ${new SchemaError(callFields()) instanceof CallError} (the explicit way to catch all four)`);
kv('UnsupportedError is a SchemaError?', `${new UnsupportedError(callFields()) instanceof SchemaError} <- peers, not a hierarchy`);
kv('artifact errors', `ArtifactError is not a CallError: ${!(new ArtifactMissingError('x') instanceof CallError)}; isChtypesError is true for both`);
kv('artifact errors', `ArtifactError is not a CallError: ${!(new ArtifactMissingError('x') instanceof CallError)}; both are ChtypesErrors: ${new ArtifactMissingError('x') instanceof ChtypesError}`);
kv('row verdicts are DATA', 'result.outcome, not a thrown error');
note('a row the server would reject RETURNS (outcome "rejected", errCode = the server\'s');
note('code): nothing throws. Exceptions are for questions that could not be asked.');
Expand Down Expand Up @@ -1298,7 +1298,7 @@ async function openOrNote(registry: Registry, line: string): Promise<Library | u
try {
return await registry.for(line);
} catch (err) {
if (!isChtypesError(err)) throw err;
if (!(err instanceof ChtypesError)) throw err;
kv(` ${line}`, `SKIPPED ${truncate(err.message, 70)}`);
return undefined;
}
Expand Down
Loading
Loading