The whole multicall `clickhouse` binary now compiles (11343 edges) and links
(a 236 MB wasm64 module) with Emscripten, and `clickhouse local` executes
queries correctly under Node.js >= 24 and in Chromium 149: MergeTree tables
on the in-memory filesystem, aggregations over 100 million rows of `numbers`
in ~2 seconds including engine startup, 1847 SQL functions, JSONEachRow from
stdin, Pretty formats. The CI job's pinned target becomes `clickhouse` and
the job provides the module as an artifact.
What it took, beyond the `dbms` step:
* `ENABLE_CAPNP` off for `OS_WASM`: its `kj` library calls `fallocate`
unconditionally in its POSIX branch, which the Emscripten libc lacks.
* Executable link options for `OS_WASM` in cmake/target.cmake: an 8 MiB shadow
stack and 256 MiB of growable memory (the defaults are 64 KiB and a fixed
16 MiB, while `clickhouse` needs ~50 MiB for static data alone); `-g0` at
the link, because binaryen's `wasm-opt` asserts in its DWARF bookkeeping
(`AddrExprMap::add`) on a module with this much debug info;
`-sPROXY_TO_PTHREAD` so `main`, which blocks its thread freely, runs on a
pthread while the browser main thread keeps servicing the event loop that
spawns the Web Workers backing new pthreads - without it the first blocking
`pthread_create` deadlocks the page; and `-sEXIT_RUNTIME` so a finished
query tears the runtime down.
* The `dlopen`-blocking override in programs/main.cpp yields on `OS_WASM`:
Emscripten's libc unconditionally defines `dlerror`, so the override was a
duplicate symbol - and a sandbox cannot load libraries in the first place.
* `initgroups` for `clickhouse-su`: the one libc symbol the entire binary
found missing. Emscripten has the other identity stubs; this one fails
closed with ENOSYS.
* Explicit `Field::safeGet<unsigned long>` and `ColumnVector::indexImpl<size_t>`
instantiations extend from `OS_DARWIN` to `OS_WASM`: both are LP64 platforms
where `uint64_t` is `unsigned long long`, so `size_t` matches no `UInt*` type.
* The `SignalListener` thread in `ClientApplicationBase` follows
`OS_HAS_SIGNAL_HANDLERS`: without signals nothing ever writes to the signal
pipe, and the blocking read of that pipe - all the thread does - fails with
EAGAIN on Emscripten, which took the whole process down through
`KillingErrorHandler`.
Known wart, upstream: after the runtime reaches `exit(0)` (verified with
`-sPTHREADS_DEBUG`), one Web Worker survives teardown and keeps the Node.js
process alive; the browser does not care.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When `arg_uid` (or `arg_gid`) is a non-numeric name that does not exist in
the passwd/group database, `tryParse` fails and leaves the local `uid`/`gid`
at its default-initialized value of 0. The "name not found" branch then
called `getpwuid_r(uid)` / `getgrgid_r(gid)`, which resolved to root and
its primary group, so `clickhouse su nosuchuser cmd` and
`clickhouse su user:nosuchgroup cmd` silently kept UID/GID 0 instead of
reporting the typo.
Only retry the numeric lookup when `tryParse` actually parsed the input as
a number (covering the legitimate `clickhouse su 0 …` / `clickhouse su :0 …`
cases). Otherwise the lookup falls through to the existing
`BAD_ARGUMENTS` "not found in the system" exception.
Address review feedback on the supplementary-group reset:
- `initgroups`/`setgroups` require `CAP_SETGID`. Calling them unconditionally
regressed non-root invocations such as the Docker `--user` path, where
`docker/server/entrypoint.sh` invokes `clickhouse su clickhouse:clickhouse`
even though the process is already running as the target user — that used
to succeed as a no-op privilege drop and now threw `SYSTEM_ERROR`. Gate
the reset on `geteuid() == 0` so it runs only when we actually have the
capability; non-root callers cannot taint their own supplementary list
anyway.
- The numeric-UID `getpwuid_r` call swallowed nonzero return codes,
treating NSS errors (`ERANGE` / `ENOMEM` / backend failures) as
"no passwd entry" and falling through to `setgroups(0, nullptr)`. Throw
on nonzero return so real lookup failures surface instead of silently
changing behavior; the `rc == 0 && result == nullptr` "no entry" case is
still allowed and clears the supplementary list.
`programs/su/su.cpp` resolves the target user and group, then calls `setgid`
followed by `setuid`. Neither syscall touches the supplementary group list,
so the dropped process silently inherits the supplementary groups of the
invoker. On a system where root has been granted membership in groups like
`disk`, `adm`, `wheel`, `docker`, `sudo`, or where the systemd unit / Docker
entrypoint configures supplementary groups, those memberships leak into the
unprivileged process and defeat the intent of the privilege drop. For
comparison, `/bin/su(1)` and `sudo(8)` both reset the supplementary list
via `initgroups` as part of dropping privileges.
Restructure `setUserAndGroup` so the passwd database is consulted even when
the UID is supplied numerically (to recover the user name), and invoke
`initgroups(user_name, group)` before `setgid`/`setuid` so the supplementary
group list reflects the target user's `/etc/group` memberships. When the
target UID has no passwd entry the supplementary list is cleared with
`setgroups(0, nullptr)` instead.
Add `static` to file-local functions and forward declarations
for cross-TU functions to satisfy `-Wmissing-prototypes`.
This ensures all functions have visible prototypes before their
definitions, improving code quality and catching accidental
linkage issues.
Reference: https://github.com/ClickHouse/ClickHouse/issues/76944
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract `ErrnoException` into `Common/ErrnoException.h` to reduce the
include footprint of `Exception.h`. This removes `<base/errnoToString.h>`
and `<cerrno>` from `Exception.h`, which is included by ~95% of all
translation units.
All files referencing `ErrnoException` now include the new header
directly. Files that used `errnoToString` without `ErrnoException`
got an explicit `<base/errnoToString.h>` include.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit improves the help output for all ClickHouse applications:
- Add `clickhouse help` command that lists all available subcommands
- Return exit code 0 for all help messages (previously some returned 1)
- Output help messages to stdout instead of stderr
- Use "clickhouse <cmd>" format instead of argv[0] in help messages
- Add dynamic `app_name` detection for `clickhouse client` and `clickhouse local`
to show correct invocation name based on how the binary was called
- Add `--no-sudo` option for `clickhouse start` and `clickhouse restart`
for environments without sudo (e.g., Docker containers)
- Add detailed help headers and footers for client and local with usage examples
Closes#58244
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Components like client/server/... are very generic, and there is no
point in disabling them, since it does not reduce amount of compiled
code a lot anyway (just a few modules for entrypoints, everything else
is already included in the clickhouse binary), and eventually they are
just symlinks to the clickhouse binary.
But there are few, that requires extra libraries, like ODBC bridge or
keeper components (and there is also standalone keeper binary compiled
with musl), those had been kept.
Also add some descriptions for some utils and change exit code to 0 for
--help.
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
* save format string for NetException
* format exceptions
* format exceptions 2
* format exceptions 3
* format exceptions 4
* format exceptions 5
* format exceptions 6
* fix
* format exceptions 7
* format exceptions 8
* Update MergeTreeIndexGin.cpp
* Update AggregateFunctionMap.cpp
* Update AggregateFunctionMap.cpp
* fix