mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-19 21:03:51 +00:00
Backport #66433 to 24.6: Fixing constants in GROUP BY keys with analyzer (again)
This commit is contained in:
parent
38f13b2cc6
commit
87a31250a2
@ -3408,14 +3408,14 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
|
|||||||
function_base = function->build(argument_columns);
|
function_base = function->build(argument_columns);
|
||||||
|
|
||||||
/// Do not constant fold get scalar functions
|
/// Do not constant fold get scalar functions
|
||||||
bool disable_constant_folding = function_name == "__getScalar" || function_name == "shardNum" ||
|
// bool disable_constant_folding = function_name == "__getScalar" || function_name == "shardNum" ||
|
||||||
function_name == "shardCount" || function_name == "hostName" || function_name == "tcpPort";
|
// function_name == "shardCount" || function_name == "hostName" || function_name == "tcpPort";
|
||||||
|
|
||||||
/** If function is suitable for constant folding try to convert it to constant.
|
/** If function is suitable for constant folding try to convert it to constant.
|
||||||
* Example: SELECT plus(1, 1);
|
* Example: SELECT plus(1, 1);
|
||||||
* Result: SELECT 2;
|
* Result: SELECT 2;
|
||||||
*/
|
*/
|
||||||
if (function_base->isSuitableForConstantFolding() && !disable_constant_folding)
|
if (function_base->isSuitableForConstantFolding()) // && !disable_constant_folding)
|
||||||
{
|
{
|
||||||
auto result_type = function_base->getResultType();
|
auto result_type = function_base->getResultType();
|
||||||
auto executable_function = function_base->prepare(argument_columns);
|
auto executable_function = function_base->prepare(argument_columns);
|
||||||
|
@ -230,6 +230,17 @@ public:
|
|||||||
|
|
||||||
virtual bool isDeterministicInScopeOfQuery() const { return true; }
|
virtual bool isDeterministicInScopeOfQuery() const { return true; }
|
||||||
|
|
||||||
|
/** This is a special flags for functions which return constant value for the server,
|
||||||
|
* but the result could be different for different servers in distributed query.
|
||||||
|
*
|
||||||
|
* This functions can't support constant folding on the initiator, but can on the follower.
|
||||||
|
* We can't apply some optimizations as well (e.g. can't remove constant result from GROUP BY key).
|
||||||
|
* So, it is convenient to have a special flag for them.
|
||||||
|
*
|
||||||
|
* Examples are: "__getScalar" and every function from serverConstants.cpp
|
||||||
|
*/
|
||||||
|
virtual bool isServerConstant() const { return false; }
|
||||||
|
|
||||||
/** Lets you know if the function is monotonic in a range of values.
|
/** Lets you know if the function is monotonic in a range of values.
|
||||||
* This is used to work with the index in a sorted chunk of data.
|
* This is used to work with the index in a sorted chunk of data.
|
||||||
* And allows to use the index not only when it is written, for example `date >= const`, but also, for example, `toMonth(date) >= 11`.
|
* And allows to use the index not only when it is written, for example `date >= const`, but also, for example, `toMonth(date) >= 11`.
|
||||||
@ -488,6 +499,7 @@ public:
|
|||||||
virtual bool isInjective(const ColumnsWithTypeAndName & /*sample_columns*/) const { return false; }
|
virtual bool isInjective(const ColumnsWithTypeAndName & /*sample_columns*/) const { return false; }
|
||||||
virtual bool isDeterministic() const { return true; }
|
virtual bool isDeterministic() const { return true; }
|
||||||
virtual bool isDeterministicInScopeOfQuery() const { return true; }
|
virtual bool isDeterministicInScopeOfQuery() const { return true; }
|
||||||
|
virtual bool isServerConstant() const { return false; }
|
||||||
virtual bool isStateful() const { return false; }
|
virtual bool isStateful() const { return false; }
|
||||||
|
|
||||||
using ShortCircuitSettings = IFunctionBase::ShortCircuitSettings;
|
using ShortCircuitSettings = IFunctionBase::ShortCircuitSettings;
|
||||||
|
@ -86,6 +86,8 @@ public:
|
|||||||
|
|
||||||
bool isDeterministicInScopeOfQuery() const override { return function->isDeterministicInScopeOfQuery(); }
|
bool isDeterministicInScopeOfQuery() const override { return function->isDeterministicInScopeOfQuery(); }
|
||||||
|
|
||||||
|
bool isServerConstant() const override { return function->isServerConstant(); }
|
||||||
|
|
||||||
bool isShortCircuit(ShortCircuitSettings & settings, size_t number_of_arguments) const override { return function->isShortCircuit(settings, number_of_arguments); }
|
bool isShortCircuit(ShortCircuitSettings & settings, size_t number_of_arguments) const override { return function->isShortCircuit(settings, number_of_arguments); }
|
||||||
|
|
||||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & args) const override { return function->isSuitableForShortCircuitArgumentsExecution(args); }
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & args) const override { return function->isSuitableForShortCircuitArgumentsExecution(args); }
|
||||||
|
@ -53,6 +53,8 @@ public:
|
|||||||
/// getMacro may return different values on different shards/replicas, so it's not constant for distributed query
|
/// getMacro may return different values on different shards/replicas, so it's not constant for distributed query
|
||||||
bool isSuitableForConstantFolding() const override { return !is_distributed; }
|
bool isSuitableForConstantFolding() const override { return !is_distributed; }
|
||||||
|
|
||||||
|
bool isServerConstant() const override { return true; }
|
||||||
|
|
||||||
size_t getNumberOfArguments() const override
|
size_t getNumberOfArguments() const override
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -49,6 +49,8 @@ public:
|
|||||||
|
|
||||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
||||||
|
|
||||||
|
bool isServerConstant() const override { return true; }
|
||||||
|
|
||||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||||
{
|
{
|
||||||
if (arguments.size() != 1 || !isString(arguments[0].type) || !arguments[0].column || !isColumnConst(*arguments[0].column))
|
if (arguments.size() != 1 || !isString(arguments[0].type) || !arguments[0].column || !isColumnConst(*arguments[0].column))
|
||||||
@ -105,6 +107,8 @@ public:
|
|||||||
|
|
||||||
bool isDeterministic() const override { return false; }
|
bool isDeterministic() const override { return false; }
|
||||||
|
|
||||||
|
bool isServerConstant() const override { return true; }
|
||||||
|
|
||||||
bool isSuitableForConstantFolding() const override { return !is_distributed; }
|
bool isSuitableForConstantFolding() const override { return !is_distributed; }
|
||||||
|
|
||||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
|
||||||
|
@ -20,117 +20,125 @@ namespace DB
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template<typename Derived, typename T, typename ColumnT>
|
||||||
|
class FunctionServerConstantBase : public FunctionConstantBase<Derived, T, ColumnT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using FunctionConstantBase<Derived, T, ColumnT>::FunctionConstantBase;
|
||||||
|
bool isServerConstant() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(__ELF__) && !defined(OS_FREEBSD)
|
#if defined(__ELF__) && !defined(OS_FREEBSD)
|
||||||
/// buildId() - returns the compiler build id of the running binary.
|
/// buildId() - returns the compiler build id of the running binary.
|
||||||
class FunctionBuildId : public FunctionConstantBase<FunctionBuildId, String, DataTypeString>
|
class FunctionBuildId : public FunctionServerConstantBase<FunctionBuildId, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "buildId";
|
static constexpr auto name = "buildId";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionBuildId>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionBuildId>(context); }
|
||||||
explicit FunctionBuildId(ContextPtr context) : FunctionConstantBase(SymbolIndex::instance().getBuildIDHex(), context->isDistributed()) {}
|
explicit FunctionBuildId(ContextPtr context) : FunctionServerConstantBase(SymbolIndex::instance().getBuildIDHex(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// Get the host name. It is constant on single server, but is not constant in distributed queries.
|
/// Get the host name. It is constant on single server, but is not constant in distributed queries.
|
||||||
class FunctionHostName : public FunctionConstantBase<FunctionHostName, String, DataTypeString>
|
class FunctionHostName : public FunctionServerConstantBase<FunctionHostName, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "hostName";
|
static constexpr auto name = "hostName";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionHostName>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionHostName>(context); }
|
||||||
explicit FunctionHostName(ContextPtr context) : FunctionConstantBase(DNSResolver::instance().getHostName(), context->isDistributed()) {}
|
explicit FunctionHostName(ContextPtr context) : FunctionServerConstantBase(DNSResolver::instance().getHostName(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FunctionServerUUID : public FunctionConstantBase<FunctionServerUUID, UUID, DataTypeUUID>
|
class FunctionServerUUID : public FunctionServerConstantBase<FunctionServerUUID, UUID, DataTypeUUID>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "serverUUID";
|
static constexpr auto name = "serverUUID";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionServerUUID>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionServerUUID>(context); }
|
||||||
explicit FunctionServerUUID(ContextPtr context) : FunctionConstantBase(ServerUUID::get(), context->isDistributed()) {}
|
explicit FunctionServerUUID(ContextPtr context) : FunctionServerConstantBase(ServerUUID::get(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FunctionTCPPort : public FunctionConstantBase<FunctionTCPPort, UInt16, DataTypeUInt16>
|
class FunctionTCPPort : public FunctionServerConstantBase<FunctionTCPPort, UInt16, DataTypeUInt16>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "tcpPort";
|
static constexpr auto name = "tcpPort";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionTCPPort>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionTCPPort>(context); }
|
||||||
explicit FunctionTCPPort(ContextPtr context) : FunctionConstantBase(context->getTCPPort(), context->isDistributed()) {}
|
explicit FunctionTCPPort(ContextPtr context) : FunctionServerConstantBase(context->getTCPPort(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Returns timezone for current session.
|
/// Returns timezone for current session.
|
||||||
class FunctionTimezone : public FunctionConstantBase<FunctionTimezone, String, DataTypeString>
|
class FunctionTimezone : public FunctionServerConstantBase<FunctionTimezone, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "timezone";
|
static constexpr auto name = "timezone";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionTimezone>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionTimezone>(context); }
|
||||||
explicit FunctionTimezone(ContextPtr context) : FunctionConstantBase(DateLUT::instance().getTimeZone(), context->isDistributed()) {}
|
explicit FunctionTimezone(ContextPtr context) : FunctionServerConstantBase(DateLUT::instance().getTimeZone(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the server time zone (timezone in which server runs).
|
/// Returns the server time zone (timezone in which server runs).
|
||||||
class FunctionServerTimezone : public FunctionConstantBase<FunctionServerTimezone, String, DataTypeString>
|
class FunctionServerTimezone : public FunctionServerConstantBase<FunctionServerTimezone, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "serverTimezone";
|
static constexpr auto name = "serverTimezone";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionServerTimezone>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionServerTimezone>(context); }
|
||||||
explicit FunctionServerTimezone(ContextPtr context) : FunctionConstantBase(DateLUT::serverTimezoneInstance().getTimeZone(), context->isDistributed()) {}
|
explicit FunctionServerTimezone(ContextPtr context) : FunctionServerConstantBase(DateLUT::serverTimezoneInstance().getTimeZone(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Returns server uptime in seconds.
|
/// Returns server uptime in seconds.
|
||||||
class FunctionUptime : public FunctionConstantBase<FunctionUptime, UInt32, DataTypeUInt32>
|
class FunctionUptime : public FunctionServerConstantBase<FunctionUptime, UInt32, DataTypeUInt32>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "uptime";
|
static constexpr auto name = "uptime";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionUptime>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionUptime>(context); }
|
||||||
explicit FunctionUptime(ContextPtr context) : FunctionConstantBase(context->getUptimeSeconds(), context->isDistributed()) {}
|
explicit FunctionUptime(ContextPtr context) : FunctionServerConstantBase(context->getUptimeSeconds(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// version() - returns the current version as a string.
|
/// version() - returns the current version as a string.
|
||||||
class FunctionVersion : public FunctionConstantBase<FunctionVersion, String, DataTypeString>
|
class FunctionVersion : public FunctionServerConstantBase<FunctionVersion, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "version";
|
static constexpr auto name = "version";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionVersion>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionVersion>(context); }
|
||||||
explicit FunctionVersion(ContextPtr context) : FunctionConstantBase(VERSION_STRING, context->isDistributed()) {}
|
explicit FunctionVersion(ContextPtr context) : FunctionServerConstantBase(VERSION_STRING, context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// revision() - returns the current revision.
|
/// revision() - returns the current revision.
|
||||||
class FunctionRevision : public FunctionConstantBase<FunctionRevision, UInt32, DataTypeUInt32>
|
class FunctionRevision : public FunctionServerConstantBase<FunctionRevision, UInt32, DataTypeUInt32>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "revision";
|
static constexpr auto name = "revision";
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionRevision>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionRevision>(context); }
|
||||||
explicit FunctionRevision(ContextPtr context) : FunctionConstantBase(ClickHouseRevision::getVersionRevision(), context->isDistributed()) {}
|
explicit FunctionRevision(ContextPtr context) : FunctionServerConstantBase(ClickHouseRevision::getVersionRevision(), context->isDistributed()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionZooKeeperSessionUptime : public FunctionConstantBase<FunctionZooKeeperSessionUptime, UInt32, DataTypeUInt32>
|
class FunctionZooKeeperSessionUptime : public FunctionServerConstantBase<FunctionZooKeeperSessionUptime, UInt32, DataTypeUInt32>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "zookeeperSessionUptime";
|
static constexpr auto name = "zookeeperSessionUptime";
|
||||||
explicit FunctionZooKeeperSessionUptime(ContextPtr context)
|
explicit FunctionZooKeeperSessionUptime(ContextPtr context)
|
||||||
: FunctionConstantBase(context->getZooKeeperSessionUptime(), context->isDistributed())
|
: FunctionServerConstantBase(context->getZooKeeperSessionUptime(), context->isDistributed())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionZooKeeperSessionUptime>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionZooKeeperSessionUptime>(context); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionGetOSKernelVersion : public FunctionConstantBase<FunctionGetOSKernelVersion, String, DataTypeString>
|
class FunctionGetOSKernelVersion : public FunctionServerConstantBase<FunctionGetOSKernelVersion, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "getOSKernelVersion";
|
static constexpr auto name = "getOSKernelVersion";
|
||||||
explicit FunctionGetOSKernelVersion(ContextPtr context) : FunctionConstantBase(Poco::Environment::osName() + " " + Poco::Environment::osVersion(), context->isDistributed()) {}
|
explicit FunctionGetOSKernelVersion(ContextPtr context) : FunctionServerConstantBase(Poco::Environment::osName() + " " + Poco::Environment::osVersion(), context->isDistributed()) {}
|
||||||
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionGetOSKernelVersion>(context); }
|
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionGetOSKernelVersion>(context); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionDisplayName : public FunctionConstantBase<FunctionDisplayName, String, DataTypeString>
|
class FunctionDisplayName : public FunctionServerConstantBase<FunctionDisplayName, String, DataTypeString>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = "displayName";
|
static constexpr auto name = "displayName";
|
||||||
explicit FunctionDisplayName(ContextPtr context) : FunctionConstantBase(context->getConfigRef().getString("display_name", getFQDNOrHostName()), context->isDistributed()) {}
|
explicit FunctionDisplayName(ContextPtr context) : FunctionServerConstantBase(context->getConfigRef().getString("display_name", getFQDNOrHostName()), context->isDistributed()) {}
|
||||||
static FunctionPtr create(ContextPtr context) {return std::make_shared<FunctionDisplayName>(context); }
|
static FunctionPtr create(ContextPtr context) {return std::make_shared<FunctionDisplayName>(context); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -83,14 +83,14 @@ bool canRemoveConstantFromGroupByKey(const ConstantNode & root)
|
|||||||
else if (function_node)
|
else if (function_node)
|
||||||
{
|
{
|
||||||
/// Do not allow removing constants like `hostName()`
|
/// Do not allow removing constants like `hostName()`
|
||||||
if (!function_node->getFunctionOrThrow()->isDeterministic())
|
if (function_node->getFunctionOrThrow()->isServerConstant())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto & child : function_node->getArguments())
|
for (const auto & child : function_node->getArguments())
|
||||||
nodes.push(child.get());
|
nodes.push(child.get());
|
||||||
}
|
}
|
||||||
else
|
// else
|
||||||
return false;
|
// return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,3 +30,46 @@ SELECT
|
|||||||
min(dummy)
|
min(dummy)
|
||||||
FROM remote('127.0.0.{2,3}', system.one)
|
FROM remote('127.0.0.{2,3}', system.one)
|
||||||
GROUP BY y;
|
GROUP BY y;
|
||||||
|
|
||||||
|
CREATE TABLE ttt (hr DateTime, ts DateTime) ENGINE=Memory
|
||||||
|
as select '2000-01-01' d, d;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
now() AS c1
|
||||||
|
FROM remote('127.0.0.{1,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1 FORMAT Null;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
now() AS c1
|
||||||
|
FROM remote('127.0.0.{3,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1 FORMAT Null;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
now() AS c1
|
||||||
|
FROM remote('127.0.0.{1,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1 + 1 FORMAT Null;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
now() AS c1
|
||||||
|
FROM remote('127.0.0.{3,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1 + 1 FORMAT Null;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
tuple(nullIf(toDateTime(formatDateTime(hr, '%F %T', 'America/Los_Angeles'), 'America/Los_Angeles'), toDateTime(0))) as c1,
|
||||||
|
defaultValueOfArgumentType(toTimeZone(ts, 'America/Los_Angeles')) as c2,
|
||||||
|
formatDateTime(hr, '%F %T', 'America/Los_Angeles') as c3
|
||||||
|
FROM remote('127.0.0.{1,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1, c2, c3 FORMAT Null;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(),
|
||||||
|
tuple(nullIf(toDateTime(formatDateTime(hr, '%F %T', 'America/Los_Angeles'), 'America/Los_Angeles'), toDateTime(0))) as c1,
|
||||||
|
defaultValueOfArgumentType(toTimeZone(ts, 'America/Los_Angeles')) as c2,
|
||||||
|
formatDateTime(hr, '%F %T', 'America/Los_Angeles') as c3
|
||||||
|
FROM remote('127.0.0.{3,2}', currentDatabase(), ttt)
|
||||||
|
GROUP BY c1, c2, c3 FORMAT Null;
|
||||||
|
Loading…
Reference in New Issue
Block a user