Skip to content

Commit

Permalink
Merge pull request #1 from Enmk/setting_timezone_on_client
Browse files Browse the repository at this point in the history
Hackish way of setting up timezone on the client
  • Loading branch information
zvonand authored Apr 11, 2023
2 parents a871c36 + e36addb commit 35f07df
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 11 deletions.
12 changes: 11 additions & 1 deletion programs/client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
#include <map>
#include <iostream>
#include <iomanip>
#include <memory>
#include <optional>
#include <string_view>
#include <Common/ThreadStatus.h>
#include <Common/scope_guard_safe.h>
#include <boost/program_options.hpp>
#include <boost/algorithm/string/replace.hpp>
Expand Down Expand Up @@ -307,7 +309,7 @@ int Client::main(const std::vector<std::string> & /*args*/)
try
{
UseSSL use_ssl;
MainThreadStatus::getInstance();
auto & thread_status = MainThreadStatus::getInstance();
setupSignalHandler();

std::cout << std::fixed << std::setprecision(3);
Expand All @@ -320,6 +322,14 @@ try
processConfig();
initTtyBuffer(toProgressOption(config().getString("progress", "default")));

{
// All that just to set DB::CurrentThread::get().getGlobalContext()
// which is required for client timezone (pushed as from server) to work.
auto thread_group = std::make_shared<ThreadGroupStatus>();
thread_group->global_context = global_context;
thread_status.attachQuery(thread_group, false);
}

/// Includes delayed_interactive.
if (is_interactive)
{
Expand Down
47 changes: 47 additions & 0 deletions src/Client/ClientBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include <Storages/ColumnsDescription.h>

#include <boost/algorithm/string/case_conv.hpp>
#include <Poco/Logger.h>
#include <iostream>
#include <filesystem>
#include <map>
Expand All @@ -73,11 +74,44 @@
#include "config_version.h"
#include "config.h"

#include <Common/logger_useful.h>


namespace fs = std::filesystem;
using namespace std::literals;


namespace
{
using namespace DB;
using ContetGetterFunc = std::function<ContextPtr(void)> const;
const void* getContextPtrOrNull(ContetGetterFunc contextFunc)
{
try
{
return contextFunc().get();
}
catch(...)
{
}
return nullptr;
}

void LogContextes(const std::string_view scope, const ContextPtr global_context)
{
const auto * context = global_context.get();
std::cerr << scope << " contextes"
<< "\n\tglobal: " << reinterpret_cast<const void*>(context)
<< "\n\tsession: " << getContextPtrOrNull([&]() { return context ? context->getSessionContext() : nullptr; })
<< "\n\tquery: " << getContextPtrOrNull([&]() { return context ? context->getQueryContext() : nullptr; })
<< "\n\tcurrent T query: " << getContextPtrOrNull([&]() { return DB::CurrentThread::get().getQueryContext(); })
<< "\n\tcurrent T global: " << getContextPtrOrNull([&]() { return DB::CurrentThread::get().getGlobalContext(); })
// << "\n\tbuffer: " << getContextPtrOrNull(context, &Context::getBufferContext)
<< std::endl;
}

}

namespace CurrentMetrics
{
extern const Metric MemoryTracking;
Expand Down Expand Up @@ -438,7 +472,12 @@ void ClientBase::onData(Block & block, ASTPtr parsed_query)
/// output_format, do not output it.
/// Also do not output too much data if we're fuzzing.
if (block.rows() == 0 || (query_fuzzer_runs != 0 && processed_rows >= 100))
{
LogContextes("ClientBase::onData header", global_context);
return;
}

LogContextes("ClientBase::onData DATA block", global_context);

/// If results are written INTO OUTFILE, we can avoid clearing progress to avoid flicker.
if (need_render_progress && tty_buf && (!select_into_file || select_into_file_and_stdout))
Expand Down Expand Up @@ -1048,7 +1087,15 @@ void ClientBase::onProgress(const Progress & value)

void ClientBase::onTimezoneUpdate(const String & tz)
{
std::cerr << "ClientBase::onTimezoneUpdate received new TZ from server: " << tz << std::endl;
DateLUT::setDefaultTimezone(tz);

Settings settings;
settings.timezone = tz;
global_context->applySettingsChanges(settings.changes());
// DB::CurrentThread::get().getQueryContext()->applySettingsChanges(settings.changes());

LogContextes("ClientBase::onTimezoneUpdate", global_context);
}


Expand Down
13 changes: 13 additions & 0 deletions src/Functions/timezoneOf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
#include <DataTypes/DataTypeDateTime.h>
#include <Common/DateLUTImpl.h>
#include <Core/Field.h>
#include "Poco/Logger.h"

#include <Common/logger_useful.h>
#include <Common/CurrentThread.h>
#include <Interpreters/Context.h>

namespace DB
{
Expand Down Expand Up @@ -52,6 +56,15 @@ class FunctionTimezoneOf : public IFunction
{
DataTypePtr type_no_nullable = removeNullable(arguments[0].type);

{
const auto query_context = DB::CurrentThread::get().getQueryContext();

LOG_DEBUG(&Poco::Logger::get("Function timezoneOf"), "query context: {}, timezone: {} ({})",
reinterpret_cast<const void*>(query_context.get()),
query_context->getSettingsRef().timezone.toString(),
(query_context->getSettingsRef().timezone.changed ? "changed" : "UNCHANGED"));
}

return DataTypeString().createColumnConst(input_rows_count,
dynamic_cast<const TimezoneMixin &>(*type_no_nullable).getTimeZone().getTimeZone());
}
Expand Down
9 changes: 9 additions & 0 deletions src/Interpreters/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
#include <rocksdb/table.h>
#endif

#include <ranges>

namespace fs = std::filesystem;

namespace ProfileEvents
Expand Down Expand Up @@ -1543,6 +1545,13 @@ void Context::applySettingChange(const SettingChange & change)
void Context::applySettingsChanges(const SettingsChanges & changes)
{
auto lock = getLock();
LOG_DEBUG(shared->log, "Context::applySettingsChanges {} applying settings changes: {}", reinterpret_cast<const void*>(this),
fmt::join(std::ranges::transform_view(changes,
[](const SettingChange & change)
{
return change.name + ": " + change.value.dump();
}), ", "));

for (const SettingChange & change : changes)
applySettingChange(change);
applySettingsQuirks(settings);
Expand Down
21 changes: 14 additions & 7 deletions src/Server/TCPHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ void TCPHandler::runImpl()
/// Send block to the client - input storage structure.
state.input_header = metadata_snapshot->getSampleBlock();
sendData(state.input_header);
sendTimezone();
});

query_context->setInputBlocksReaderCallback([this] (ContextPtr context) -> Block
Expand Down Expand Up @@ -452,9 +453,7 @@ void TCPHandler::runImpl()
if (isQueryCancelled())
return true;

if (client_tcp_protocol_version >= DBMS_MIN_PROTOCOL_VERSION_WITH_TIMEZONE_UPDATES
&& client_tcp_protocol_version >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE)
sendTimezone();
// sendTimezone();
sendProgress();
sendSelectProfileEvents();
sendLogs();
Expand Down Expand Up @@ -496,9 +495,7 @@ void TCPHandler::runImpl()

{
std::lock_guard lock(task_callback_mutex);
if (client_tcp_protocol_version >= DBMS_MIN_PROTOCOL_VERSION_WITH_TIMEZONE_UPDATES
&& client_tcp_protocol_version >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE)
sendTimezone();
// sendTimezone();
sendLogs();
sendEndOfStream();
}
Expand Down Expand Up @@ -764,7 +761,7 @@ void TCPHandler::processInsertQuery()

/// Send block to the client - table structure.
sendData(executor.getHeader());

sendTimezone();
sendLogs();

while (readDataNext())
Expand Down Expand Up @@ -809,6 +806,7 @@ void TCPHandler::processOrdinaryQueryWithProcessors()
{
std::lock_guard lock(task_callback_mutex);
sendData(header);
sendTimezone();
}
}

Expand Down Expand Up @@ -1061,7 +1059,16 @@ void TCPHandler::sendInsertProfileEvents()

void TCPHandler::sendTimezone()
{
// if (client_tcp_protocol_version <= DBMS_MIN_PROTOCOL_VERSION_WITH_TIMEZONE_UPDATES
// || client_tcp_protocol_version <= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE)
// return;

// const String & tz = CurrentThread::get().getQueryContext()->getSettingsRef().timezone.toString();
LOG_DEBUG(log, "TCPHandler::sendTimezone() query context: {}, timezone: {} ({})",
reinterpret_cast<const void*>(query_context.get()),
query_context->getSettingsRef().timezone.toString(),
(query_context->getSettingsRef().timezone.changed ? "changed" : "UNCHANGED"));

const String & tz = query_context->getSettingsRef().timezone.toString();
if (!tz.empty())
{
Expand Down
8 changes: 5 additions & 3 deletions tests/queries/0_stateless/02668_timezone_setting.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
SET timezone = 'Абырвалг'; -- { serverError BAD_ARGUMENTS}

SET timezone = 'Asia/Novosibirsk';
SELECT toDateTime64(toDateTime64('1999-12-12 23:23:23.123', 3), 3, 'Europe/Zurich');
SELECT toDateTime64(toDateTime64('1999-12-12 23:23:23.123', 3), 3, 'Europe/Zurich') SETTINGS timezone = 'Europe/Zurich';

SET timezone = 'Europe/Zurich';
SET timezone = 'Asia/Manila';
SELECT toDateTime64(toDateTime64('1999-12-12 23:23:23.123', 3), 3, 'Asia/Novosibirsk');

SET timezone = 'Абырвалг';
select now(); -- { serverError POCO_EXCEPTION }
SELECT timezone(), serverTimeZone(), timezoneOf(now()) SETTINGS timezone = 'Europe/Zurich';
SELECT timezone(), serverTimeZone(), timezoneOf(now()) SETTINGS timezone = 'Pacific/Pitcairn';

0 comments on commit 35f07df

Please sign in to comment.