Files
zeekay 286f257aae De-brand the client: clickhouse-cpp -> datastore-cpp
Pure rename applied on top of upstream tag v2.6.2 (8d2415d6), not HEAD.
The fork was cut at 737145d = v2.6.2-57, which still declared version 2.6.2
in version.h; renaming there would have shipped 57 unreleased commits wearing
a 2.6.2 label. Reset to the tag first so this commit changes names only.

  clickhouse/            -> datastore/            (public include root)
  namespace clickhouse   -> namespace datastore
  CLICKHOUSE_CPP_VERSION -> DATASTORE_CPP_VERSION
  clickhouse-cpp-lib/-ut -> datastore-cpp-lib/-ut (CMake, Bazel)
  CH_MAP_BOOL_TO_UINT8   -> DS_MAP_BOOL_TO_UINT8
  CLICKHOUSE_*           -> DATASTORE_*           (test env vars)
  doc links              -> docs.hanzo.ai/datastore

This client speaks the NATIVE binary protocol only - there is no HTTP path
and no X-ClickHouse-* header anywhere in it, so the header rename that the
HTTP clients required does not apply and nothing here was broken.

The one string that reaches the wire is CLIENT_NAME, sent by both SendHello
and SendQuery's ClientInfo from a single macro, and it lands in
system.query_log.client_name. Both sites still read the one macro, so they
stay consistent and the server's Hello/Query consistency check is satisfied.
Old rows keep the old name; that is a reporting discontinuity, not a
migration, since nothing keys on it.

CI is repointed at our own server: ghcr.io/hanzoai/datastore:26.2.3.2, the
image production runs. Its entrypoint honours DATASTORE_SKIP_USER_SETUP, not
the CLICKHOUSE_ spelling the compose file used, and its config lives in
/etc/hanzo-datastore-server. ci/docker-compose/config.xml is now layered in
as a config.d drop-in so the image keeps its own white-labelling. That file
and users.xml deliberately keep a <clickhouse> root: it must match the roots
of the drop-ins the image ships, and a mismatch fails silently - the server
logs "Merging bypassed" and starts with every drop-in discarded.

The remote-TLS suites used to default to the third-party host
play.clickhouse.com. They now read DATASTORE_SECURE*_HOST and skip when it is
unset rather than point at a host we do not run.

Dropped as upstream infrastructure with no meaning here: AI_POLICY.md
(upstream's policy about their codebase), .travis.yml (dead CI referencing a
third-party apt repo), cross-repo-bug-relay.yml (relays our issues into an
upstream triage repo). LICENSE keeps its copyright notice, as Apache-2.0
requires.

Verified: cmake configure + 115-target build clean; the full suite is green
against ghcr.io/hanzoai/datastore:26.2.3.2 (894 passed, 0 failed); the
pristine v2.6.2 build run against that same server passes the identical set,
and both logged the same 3914 queries under their respective client names.
2026-07-26 11:44:39 -07:00

212 lines
6.5 KiB
C++

#pragma once
#include <datastore/base/platform.h>
#include <datastore/base/uuid.h>
#include "datastore/columns/itemview.h"
#include "datastore/query.h"
#include "utils_meta.h"
#include "utils_comparison.h"
#include <iterator>
#include <optional>
#include <ostream>
#include <ratio>
#include <string_view>
#include <system_error>
#include <type_traits>
#include <vector>
#include <cmath>
#include <time.h>
#include <gtest/gtest.h>
namespace datastore {
class Client;
class Block;
class Type;
struct ServerInfo;
struct Profile;
struct QuerySettingsField;
struct Progress;
}
template <typename ResultType = std::string>
auto getEnvOrDefault(const std::string& env, const char * default_val) {
const char* v = std::getenv(env.c_str());
if (!v && !default_val)
throw std::runtime_error("Environment var '" + env + "' is not set.");
const std::string value = v ? v : default_val;
if constexpr (std::is_same_v<ResultType, std::string>) {
return value;
} else if constexpr (std::is_integral_v<ResultType>) {
// since std::from_chars is not available on GCC-7 on linux
if constexpr (std::is_signed_v<ResultType>) {
if constexpr (sizeof(ResultType) <= sizeof(int))
return std::stoi(value);
else if constexpr (sizeof(ResultType) <= sizeof(long))
return std::stol(value);
else if constexpr (sizeof(ResultType) <= sizeof(long long))
return std::stoll(value);
} else if constexpr (std::is_unsigned_v<ResultType>) {
if constexpr (sizeof(ResultType) <= sizeof(unsigned long))
// For cases when ResultType is unsigned int.
return static_cast<ResultType>(std::stoul(value));
else if constexpr (sizeof(ResultType) <= sizeof(unsigned long long))
return std::stoull(value);
}
}
}
template <typename R>
inline const char * getPrefix() {
const char * prefix = "?";
if constexpr (std::ratio_equal_v<R, std::nano>) {
prefix = "n";
} else if constexpr (std::ratio_equal_v<R, std::micro>) {
prefix = "u";
} else if constexpr (std::ratio_equal_v<R, std::milli>) {
prefix = "m";
} else if constexpr (std::ratio_equal_v<R, std::centi>) {
prefix = "c";
} else if constexpr (std::ratio_equal_v<R, std::deci>) {
prefix = "d";
} else if constexpr (std::ratio_equal_v<R, std::ratio<1, 1>>) {
prefix = "";
} else {
static_assert("Unsupported ratio");
}
return prefix;
}
template <typename T, size_t index = std::tuple_size_v<T> >
inline std::ostream & printTuple(std::ostream & ostr, [[maybe_unused]] const T & t) {
static_assert(index <= std::tuple_size_v<T>);
if constexpr (index == 0) {
return ostr << "( ";
} else {
printTuple<T, index - 1>(ostr, t);
using ElementType = std::tuple_element_t<index - 1, T>;
if constexpr (is_container_v<ElementType>) {
ostr << PrintContainer{std::get<index - 1>(t)};
} else {
ostr << std::get<0>(t);
}
if constexpr (index == std::tuple_size_v<T>) {
return ostr << " )";
} else {
return ostr << ", ";
}
}
}
namespace std {
template <typename R, typename P>
inline ostream & operator<<(ostream & ostr, const chrono::duration<R, P> & d) {
return ostr << d.count() << ::getPrefix<P>() << "s";
}
template <typename F, typename S>
inline ostream & operator<<(ostream & ostr, const pair<F, S> & t) {
return ostr << "{ " << t.first << ", " << t.second << " }";
}
template <typename ... T>
inline ostream & operator<<(ostream & ostr, const tuple<T...> & t) {
return printTuple(ostr, t);
}
template <typename T>
inline ostream & operator<<(ostream & ostr, const optional<T> & t) {
if (t.has_value()) {
return ostr << *t;
} else {
return ostr << "NULL";
}
}
}
struct in_addr;
struct in6_addr;
// Helper for pretty-printing of the Block
struct PrettyPrintBlock {
const datastore::Block & block;
};
namespace datastore {
std::ostream& operator<<(std::ostream & ostr, const Block & block);
std::ostream& operator<<(std::ostream & ostr, const Type & type);
std::ostream & operator<<(std::ostream & ostr, const ServerInfo & server_info);
std::ostream & operator<<(std::ostream & ostr, const Profile & profile);
std::ostream & operator<<(std::ostream & ostr, const Progress & progress);
std::ostream & operator<<(std::ostream& ostr, const ItemView& item_view);
}
std::ostream& operator<<(std::ostream & ostr, const PrettyPrintBlock & block);
std::ostream& operator<<(std::ostream& ostr, const in_addr& addr);
std::ostream& operator<<(std::ostream& ostr, const in6_addr& addr);
template <typename Container>
struct PrintContainer {
const Container & container_;
explicit PrintContainer(const Container& container)
: container_(container)
{}
};
template <typename T>
std::ostream& operator<<(std::ostream & ostr, const PrintContainer<T>& print_container) {
ostr << "[";
const auto & container = print_container.container_;
for (auto i = std::begin(container); i != std::end(container); /*intentionally no ++i*/) {
const auto & elem = *i;
if constexpr (is_string_v<decltype(elem)>) {
ostr << '"' << elem << '"';
}
else if constexpr (is_container_v<std::decay_t<decltype(elem)>>) {
ostr << PrintContainer{elem};
} else {
ostr << elem;
}
if (++i != std::end(container)) {
ostr << ", ";
}
}
return ostr << "] (" << std::size(container) << " items)";
}
inline uint64_t versionNumber(
uint64_t version_major,
uint64_t version_minor,
uint64_t version_patch = 0,
uint64_t revision = 0) {
// in this case version_major can be up to 1000
static auto revision_decimal_places = 8;
static auto patch_decimal_places = 4;
static auto minor_decimal_places = 4;
auto const result = version_major * static_cast<uint64_t>(std::pow(10, minor_decimal_places + patch_decimal_places + revision_decimal_places))
+ version_minor * static_cast<uint64_t>(std::pow(10, patch_decimal_places + revision_decimal_places))
+ version_patch * static_cast<uint64_t>(std::pow(10, revision_decimal_places))
+ revision;
return result;
}
uint64_t versionNumber(const datastore::ServerInfo & server_info);
std::string ToString(const datastore::UUID& v);