提交 3d4906e0 编写于 作者: A Alexey Milovidov

Merge branch 'master' of https://github.com/kshvakov/ClickHouse-Server into kshvakov-master

......@@ -19,6 +19,6 @@
[submodule "contrib/zlib-ng"]
path = contrib/zlib-ng
url = https://github.com/Dead2/zlib-ng.git
[submodule "contrib/googletest"]
path = contrib/googletest
url = https://github.com/google/googletest.git
[submodule "contrib/googletest"]
path = contrib/googletest
url = https://github.com/google/googletest.git
\ No newline at end of file
Subproject commit d175c8bf823e709d570772b038757fadf63bc632
......@@ -72,6 +72,7 @@ void registerFunctionsDateTime(FunctionFactory & factory)
factory.registerFunction<FunctionToStartOfYear>();
factory.registerFunction<FunctionToStartOfMinute>();
factory.registerFunction<FunctionToStartOfFiveMinute>();
factory.registerFunction<FunctionToStartOfFifteenMinutes>();
factory.registerFunction<FunctionToStartOfHour>();
factory.registerFunction<FunctionToRelativeYearNum>();
factory.registerFunction<FunctionToRelativeQuarterNum>();
......
......@@ -37,7 +37,7 @@ namespace ErrorCodes
/** Functions for working with date and time.
*
* toYear, toMonth, toDayOfMonth, toDayOfWeek, toHour, toMinute, toSecond,
* toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfFiveMinute
* toMonday, toStartOfMonth, toStartOfYear, toStartOfMinute, toStartOfFiveMinute, toStartOfFifteenMinutes
* toStartOfHour, toTime,
* now, today, yesterday
* TODO: makeDate, makeDateTime
......@@ -238,6 +238,22 @@ struct ToStartOfFiveMinuteImpl
using FactorTransform = ZeroTransform;
};
struct ToStartOfFifteenMinutesImpl
{
static constexpr auto name = "toStartOfFifteenMinutes";
static inline UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toStartOfFifteenMinutes(t);
}
static inline UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
throw Exception("Illegal type Date of argument for function toStartOfFifteenMinutes", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
using FactorTransform = ZeroTransform;
};
struct ToStartOfHourImpl
{
static constexpr auto name = "toStartOfHour";
......@@ -1510,6 +1526,7 @@ using FunctionToStartOfQuarter = FunctionDateOrDateTimeToSomething<DataTypeDate,
using FunctionToStartOfYear = FunctionDateOrDateTimeToSomething<DataTypeDate, ToStartOfYearImpl>;
using FunctionToStartOfMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfMinuteImpl>;
using FunctionToStartOfFiveMinute = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFiveMinuteImpl>;
using FunctionToStartOfFifteenMinutes = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfFifteenMinutesImpl>;
using FunctionToStartOfHour = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToStartOfHourImpl>;
using FunctionToTime = FunctionDateOrDateTimeToSomething<DataTypeDateTime, ToTimeImpl>;
......
......@@ -8,19 +8,19 @@
#include <IO/WriteBufferFromFile.h>
#include <IO/WriteHelpers.h>
#include <DataStreams/AddingDefaultBlockOutputStream.h>
#include <DataStreams/MaterializingBlockOutputStream.h>
#include <DataStreams/NullAndDoCopyBlockInputStream.h>
#include <DataStreams/ProhibitColumnsBlockOutputStream.h>
#include <DataStreams/MaterializingBlockOutputStream.h>
#include <DataStreams/AddingDefaultBlockOutputStream.h>
#include <DataStreams/PushingToViewsBlockOutputStream.h>
#include <Parsers/ASTCreateQuery.h>
#include <Parsers/ASTNameTypePair.h>
#include <Parsers/ASTColumnDeclaration.h>
#include <Parsers/formatAST.h>
#include <Parsers/ASTCreateQuery.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTNameTypePair.h>
#include <Parsers/ParserCreateQuery.h>
#include <Parsers/formatAST.h>
#include <Parsers/parseQuery.h>
#include <Parsers/queryToString.h>
......@@ -28,14 +28,14 @@
#include <Storages/StorageLog.h>
#include <Interpreters/Context.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterCreateQuery.h>
#include <Interpreters/ExpressionAnalyzer.h>
#include <Interpreters/DDLWorker.h>
#include <Interpreters/ExpressionAnalyzer.h>
#include <Interpreters/InterpreterCreateQuery.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeNested.h>
#include <DataTypes/DataTypeFactory.h>
#include <DataTypes/DataTypeNested.h>
#include <DataTypes/DataTypesNumber.h>
#include <Databases/DatabaseFactory.h>
#include <Databases/IDatabase.h>
......@@ -44,7 +44,6 @@
namespace DB
{
namespace ErrorCodes
{
extern const int DIRECTORY_DOESNT_EXIST;
......@@ -56,17 +55,20 @@ namespace ErrorCodes
extern const int TABLE_METADATA_ALREADY_EXISTS;
extern const int UNKNOWN_DATABASE_ENGINE;
extern const int DUPLICATE_COLUMN;
extern const int READONLY;
}
InterpreterCreateQuery::InterpreterCreateQuery(const ASTPtr & query_ptr_, Context & context_)
: query_ptr(query_ptr_), context(context_)
{
}
InterpreterCreateQuery::InterpreterCreateQuery(const ASTPtr & query_ptr_, Context & context_)
: query_ptr(query_ptr_), context(context_)
{
}
BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
{
checkAccess(create);
if (!create.cluster.empty())
return executeDDLQueryOnCluster(query_ptr, context);
......@@ -78,7 +80,7 @@ BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
String database_engine_name;
if (!create.storage)
{
database_engine_name = "Ordinary"; /// Default database engine.
database_engine_name = "Ordinary"; /// Default database engine.
auto engine = std::make_shared<ASTFunction>();
engine->name = database_engine_name;
auto storage = std::make_shared<ASTStorage>();
......@@ -90,8 +92,7 @@ BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
const ASTStorage & storage = *create.storage;
const ASTFunction & engine = *storage.engine;
/// Currently, there are no database engines, that support any arguments.
if (engine.arguments || engine.parameters
|| storage.partition_by || storage.order_by || storage.sample_by || storage.settings)
if (engine.arguments || engine.parameters || storage.partition_by || storage.order_by || storage.sample_by || storage.settings)
{
std::stringstream ostr;
formatAST(storage, ostr, false, false);
......@@ -256,12 +257,11 @@ static ColumnsAndDefaults parseColumns(const ASTExpressionList & column_list_ast
}
}
return { *DataTypeNested::expandNestedColumns(columns), defaults };
return {*DataTypeNested::expandNestedColumns(columns), defaults};
}
static NamesAndTypesList removeAndReturnColumns(
ColumnsAndDefaults & columns_and_defaults, const ColumnDefaultType type)
static NamesAndTypesList removeAndReturnColumns(ColumnsAndDefaults & columns_and_defaults, const ColumnDefaultType type)
{
auto & columns = columns_and_defaults.first;
auto & defaults = columns_and_defaults.second;
......@@ -345,8 +345,7 @@ ASTPtr InterpreterCreateQuery::formatColumns(NamesAndTypesList columns,
}
InterpreterCreateQuery::ColumnsInfo InterpreterCreateQuery::getColumnsInfo(
const ASTExpressionList & columns, const Context & context)
InterpreterCreateQuery::ColumnsInfo InterpreterCreateQuery::getColumnsInfo(const ASTExpressionList & columns, const Context & context)
{
ColumnsInfo res;
......@@ -446,7 +445,7 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
if (as_create.is_view)
throw Exception(
"Cannot CREATE a table AS " + as_database_name + "." + as_table_name + ", it is a View",
"Cannot CREATE a table AS " + as_database_name + "." + as_table_name + ", it is a View",
ErrorCodes::INCORRECT_QUERY);
create.set(create.storage, as_create.storage->ptr());
......@@ -456,6 +455,8 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
{
checkAccess(create);
if (!create.cluster.empty())
return executeDDLQueryOnCluster(query_ptr, context);
......@@ -525,7 +526,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
* Otherwise, concurrent queries for creating a table, if the table does not exist,
* can throw an exception, even if IF NOT EXISTS is specified.
*/
guard = context.getDDLGuardIfTableDoesntExist(database_name, table_name,
guard = context.getDDLGuardIfTableDoesntExist(database_name, table_name,
"Table " + database_name + "." + table_name + " is creating or attaching right now");
if (!guard)
......@@ -537,10 +538,18 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
}
}
res = StorageFactory::instance().get(
create, data_path, table_name, database_name, context, context.getGlobalContext(),
columns.columns, columns.materialized_columns, columns.alias_columns, columns.column_defaults,
create.attach, false);
res = StorageFactory::instance().get(create,
data_path,
table_name,
database_name,
context,
context.getGlobalContext(),
columns.columns,
columns.materialized_columns,
columns.alias_columns,
columns.column_defaults,
create.attach,
false);
if (create.is_temporary)
context.getSessionContext().addExternalTable(table_name, res);
......@@ -593,5 +602,27 @@ BlockIO InterpreterCreateQuery::execute()
return createTable(create);
}
void InterpreterCreateQuery::checkAccess(const ASTCreateQuery & create)
{
const Settings & settings = context.getSettingsRef();
auto readonly = settings.limits.readonly;
if (!readonly)
{
return;
}
/// CREATE|ATTACH DATABASE
if (!create.database.empty() && create.table.empty())
{
throw Exception("Cannot create database in readonly mode", ErrorCodes::READONLY);
}
if (create.is_temporary && readonly >= 2)
{
return;
}
throw Exception("Cannot create table in readonly mode", ErrorCodes::READONLY);
}
}
......@@ -8,7 +8,6 @@ class ThreadPool;
namespace DB
{
class Context;
class ASTCreateQuery;
class ASTExpressionList;
......@@ -28,8 +27,7 @@ public:
/// List of columns and their types in AST.
static ASTPtr formatColumns(const NamesAndTypesList & columns);
static ASTPtr formatColumns(
NamesAndTypesList columns,
static ASTPtr formatColumns(NamesAndTypesList columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults);
......@@ -62,7 +60,8 @@ private:
/// Calculate list of columns of table and return it.
ColumnsInfo setColumns(ASTCreateQuery & create, const Block & as_select_sample, const StoragePtr & as_storage) const;
void setEngine(ASTCreateQuery & create) const;
void checkAccess(const ASTCreateQuery & create);
ASTPtr query_ptr;
Context & context;
......@@ -72,6 +71,4 @@ private:
/// Skip safety threshold when loading tables.
bool has_force_restore_data_flag = false;
};
}
#include <Poco/File.h>
#include <Common/escapeForFileName.h>
#include <Common/typeid_cast.h>
#include <Parsers/ASTDropQuery.h>
#include <Databases/IDatabase.h>
#include <Interpreters/Context.h>
#include <Interpreters/DDLWorker.h>
#include <Interpreters/InterpreterDropQuery.h>
#include <Parsers/ASTDropQuery.h>
#include <Storages/IStorage.h>
#include <Databases/IDatabase.h>
#include <Interpreters/DDLWorker.h>
#include <Common/escapeForFileName.h>
#include <Common/typeid_cast.h>
namespace DB
{
namespace ErrorCodes
{
extern const int TABLE_WAS_NOT_DROPPED;
extern const int DATABASE_NOT_EMPTY;
extern const int UNKNOWN_DATABASE;
extern const int READONLY;
}
InterpreterDropQuery::InterpreterDropQuery(const ASTPtr & query_ptr_, Context & context_)
: query_ptr(query_ptr_), context(context_)
{
}
InterpreterDropQuery::InterpreterDropQuery(const ASTPtr & query_ptr_, Context & context_) : query_ptr(query_ptr_), context(context_) {}
BlockIO InterpreterDropQuery::execute()
{
ASTDropQuery & drop = typeid_cast<ASTDropQuery &>(*query_ptr);
checkAccess(drop);
if (!drop.cluster.empty())
return executeDDLQueryOnCluster(query_ptr, context);
......@@ -71,9 +70,7 @@ BlockIO InterpreterDropQuery::execute()
if (!database && !drop.if_exists)
throw Exception("Database " + database_name + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE);
std::vector<std::pair<
StoragePtr,
std::unique_ptr<DDLGuard>>> tables_to_drop;
std::vector<std::pair<StoragePtr, std::unique_ptr<DDLGuard>>> tables_to_drop;
if (!drop_database)
{
......@@ -85,8 +82,9 @@ BlockIO InterpreterDropQuery::execute()
table = context.getTable(database_name, drop.table);
if (table)
tables_to_drop.emplace_back(table, context.getDDLGuard(database_name, drop.table,
"Table " + database_name + "." + drop.table + " is dropping or detaching right now"));
tables_to_drop.emplace_back(table,
context.getDDLGuard(
database_name, drop.table, "Table " + database_name + "." + drop.table + " is dropping or detaching right now"));
else
return {};
}
......@@ -100,8 +98,10 @@ BlockIO InterpreterDropQuery::execute()
}
for (auto iterator = database->getIterator(context); iterator->isValid(); iterator->next())
tables_to_drop.emplace_back(iterator->table(), context.getDDLGuard(database_name, iterator->name(),
"Table " + database_name + "." + iterator->name() + " is dropping or detaching right now"));
tables_to_drop.emplace_back(iterator->table(),
context.getDDLGuard(database_name,
iterator->name(),
"Table " + database_name + "." + iterator->name() + " is dropping or detaching right now"));
}
for (auto & table : tables_to_drop)
......@@ -109,8 +109,8 @@ BlockIO InterpreterDropQuery::execute()
if (!drop.detach)
{
if (!table.first->checkTableCanBeDropped())
throw Exception("Table " + database_name + "." + table.first->getTableName() + " couldn't be dropped due to failed pre-drop check",
ErrorCodes::TABLE_WAS_NOT_DROPPED);
throw Exception("Table " + database_name + "." + table.first->getTableName() + " couldn't be dropped due to failed pre-drop check",
ErrorCodes::TABLE_WAS_NOT_DROPPED);
}
table.first->shutdown();
......@@ -167,5 +167,16 @@ BlockIO InterpreterDropQuery::execute()
return {};
}
void InterpreterDropQuery::checkAccess(const ASTDropQuery & drop)
{
const Settings & settings = context.getSettingsRef();
auto readonly = settings.limits.readonly;
if (!readonly || (drop.database.empty() && context.tryGetExternalTable(drop.table) && readonly >= 2))
{
return;
}
throw Exception("Cannot drop table in readonly mode", ErrorCodes::READONLY);
}
}
#pragma once
#include <Interpreters/IInterpreter.h>
#include <Parsers/ASTDropQuery.h>
namespace DB
{
class Context;
class IAST;
using ASTPtr = std::shared_ptr<IAST>;
......@@ -22,9 +22,8 @@ public:
BlockIO execute() override;
private:
void checkAccess(const ASTDropQuery & drop);
ASTPtr query_ptr;
Context & context;
};
}
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTAlterQuery.h>
#include <Parsers/ASTCheckQuery.h>
#include <Parsers/ASTCreateQuery.h>
#include <Parsers/ASTDropQuery.h>
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTKillQueryQuery.h>
#include <Parsers/ASTOptimizeQuery.h>
#include <Parsers/ASTRenameQuery.h>
#include <Parsers/ASTShowTablesQuery.h>
#include <Parsers/ASTUseQuery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTSetQuery.h>
#include <Parsers/ASTOptimizeQuery.h>
#include <Parsers/ASTAlterQuery.h>
#include <Parsers/ASTShowProcesslistQuery.h>
#include <Parsers/ASTShowTablesQuery.h>
#include <Parsers/ASTUseQuery.h>
#include <Parsers/TablePropertiesQueriesASTs.h>
#include <Parsers/ASTCheckQuery.h>
#include <Parsers/ASTKillQueryQuery.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <Interpreters/InterpreterAlterQuery.h>
#include <Interpreters/InterpreterCheckQuery.h>
#include <Interpreters/InterpreterCreateQuery.h>
#include <Interpreters/InterpreterDescribeQuery.h>
#include <Interpreters/InterpreterDropQuery.h>
#include <Interpreters/InterpreterExistsQuery.h>
#include <Interpreters/InterpreterFactory.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <Interpreters/InterpreterKillQueryQuery.h>
#include <Interpreters/InterpreterOptimizeQuery.h>
#include <Interpreters/InterpreterRenameQuery.h>
#include <Interpreters/InterpreterShowTablesQuery.h>
#include <Interpreters/InterpreterUseQuery.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterSetQuery.h>
#include <Interpreters/InterpreterOptimizeQuery.h>
#include <Interpreters/InterpreterExistsQuery.h>
#include <Interpreters/InterpreterDescribeQuery.h>
#include <Interpreters/InterpreterShowCreateQuery.h>
#include <Interpreters/InterpreterAlterQuery.h>
#include <Interpreters/InterpreterShowProcesslistQuery.h>
#include <Interpreters/InterpreterCheckQuery.h>
#include <Interpreters/InterpreterKillQueryQuery.h>
#include <Interpreters/InterpreterShowTablesQuery.h>
#include <Interpreters/InterpreterSystemQuery.h>
#include <Interpreters/InterpreterFactory.h>
#include <Interpreters/InterpreterUseQuery.h>
#include <Common/typeid_cast.h>
#include <Parsers/ASTSystemQuery.h>
#include <Common/typeid_cast.h>
namespace DB
{
namespace ErrorCodes
{
extern const int READONLY;
......@@ -61,17 +60,17 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
}
else if (typeid_cast<ASTInsertQuery *>(query.get()))
{
throwIfReadOnly(context);
/// readonly is checked inside InterpreterInsertQuery
return std::make_unique<InterpreterInsertQuery>(query, context);
}
else if (typeid_cast<ASTCreateQuery *>(query.get()))
{
throwIfReadOnly(context);
/// readonly is checked inside InterpreterCreateQuery
return std::make_unique<InterpreterCreateQuery>(query, context);
}
else if (typeid_cast<ASTDropQuery *>(query.get()))
{
throwIfReadOnly(context);
/// readonly is checked inside InterpreterDropQuery
return std::make_unique<InterpreterDropQuery>(query, context);
}
else if (typeid_cast<ASTRenameQuery *>(query.get()))
......@@ -134,5 +133,4 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
else
throw Exception("Unknown type of query: " + query->getID(), ErrorCodes::UNKNOWN_TYPE_OF_QUERY);
}
}
......@@ -2,38 +2,38 @@
#include <Common/typeid_cast.h>
#include <DataStreams/ProhibitColumnsBlockOutputStream.h>
#include <DataStreams/MaterializingBlockOutputStream.h>
#include <DataStreams/AddingDefaultBlockOutputStream.h>
#include <DataStreams/PushingToViewsBlockOutputStream.h>
#include <DataStreams/NullAndDoCopyBlockInputStream.h>
#include <DataStreams/SquashingBlockOutputStream.h>
#include <DataStreams/CastTypeBlockInputStream.h>
#include <DataStreams/CountingBlockOutputStream.h>
#include <DataStreams/MaterializingBlockOutputStream.h>
#include <DataStreams/NullAndDoCopyBlockInputStream.h>
#include <DataStreams/NullableAdapterBlockInputStream.h>
#include <DataStreams/CastTypeBlockInputStream.h>
#include <DataStreams/ProhibitColumnsBlockOutputStream.h>
#include <DataStreams/PushingToViewsBlockOutputStream.h>
#include <DataStreams/SquashingBlockOutputStream.h>
#include <DataStreams/copyData.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTIdentifier.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <Interpreters/InterpreterSelectQuery.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <Parsers/ASTFunction.h>
namespace ProfileEvents
{
extern const Event InsertQuery;
extern const Event InsertQuery;
}
namespace DB
{
namespace ErrorCodes
{
extern const int NO_SUCH_COLUMN_IN_TABLE;
extern const int READONLY;
}
......@@ -101,6 +101,7 @@ Block InterpreterInsertQuery::getSampleBlock()
BlockIO InterpreterInsertQuery::execute()
{
ASTInsertQuery & query = typeid_cast<ASTInsertQuery &>(*query_ptr);
checkAccess(query);
StoragePtr table = getTable();
auto table_lock = table->lockStructure(true, __PRETTY_FUNCTION__);
......@@ -114,14 +115,13 @@ BlockIO InterpreterInsertQuery::execute()
out = std::make_shared<MaterializingBlockOutputStream>(out);
out = std::make_shared<AddingDefaultBlockOutputStream>(out,
required_columns, table->column_defaults, context, static_cast<bool>(context.getSettingsRef().strict_insert_defaults));
out = std::make_shared<AddingDefaultBlockOutputStream>(
out, required_columns, table->column_defaults, context, static_cast<bool>(context.getSettingsRef().strict_insert_defaults));
out = std::make_shared<ProhibitColumnsBlockOutputStream>(out, table->materialized_columns);
out = std::make_shared<SquashingBlockOutputStream>(out,
context.getSettingsRef().min_insert_block_size_rows,
context.getSettingsRef().min_insert_block_size_bytes);
out = std::make_shared<SquashingBlockOutputStream>(
out, context.getSettingsRef().min_insert_block_size_rows, context.getSettingsRef().min_insert_block_size_bytes);
auto out_wrapper = std::make_shared<CountingBlockOutputStream>(out);
out_wrapper->setProcessListElement(context.getProcessListElement());
......@@ -150,5 +150,16 @@ BlockIO InterpreterInsertQuery::execute()
return res;
}
void InterpreterInsertQuery::checkAccess(const ASTInsertQuery & query)
{
const Settings & settings = context.getSettingsRef();
auto readonly = settings.limits.readonly;
if (!readonly || (query.database.empty() && context.tryGetExternalTable(query.table) && readonly >= 2))
{
return;
}
throw Exception("Cannot insert into table in readonly mode", ErrorCodes::READONLY);
}
}
......@@ -4,7 +4,7 @@
#include <DataStreams/BlockIO.h>
#include <Interpreters/Context.h>
#include <Interpreters/IInterpreter.h>
#include <Parsers/ASTInsertQuery.h>
namespace DB
{
......@@ -33,6 +33,8 @@ private:
Block getSampleBlock();
void checkAccess(const ASTInsertQuery & query);
ASTPtr query_ptr;
const Context & context;
};
......
......@@ -36,6 +36,7 @@
<value>toStartOfMinute</value>
<value>toStartOfFiveMinute</value>
<value>toStartOfFifteenMinutes</value>
<value>toStartOfHour</value>
<value>toStartOfDay</value>
<value>toDate</value>
......
......@@ -83,6 +83,10 @@ toStartOfFiveMinute
~~~~~~~~~~~~~~~~~~~
Rounds down a date with time to the start of the 5 minute (00:00, 00:05, 00:10...).
toStartOfFifteenMinutes
~~~~~~~~~~~~~~~~~~~
Rounds down a date with time to the start of the 15 minutes (00:00, 00:15, 00:30...).
toStartOfHour
~~~~~~~~~~~~~
Rounds down a date with time to the start of the hour.
......
......@@ -66,6 +66,9 @@ SELECT
## toStartOfFiveMinute
Округляет дату-с-временем вниз до начала пятиминутного интервала.
## toStartOfFifteenMinutes
Округляет дату-с-временем вниз до начала пятнадцатиминутного интервала.
Замечание: если вам нужно округлить дату-с-временем до какого-либо другого количества секунд, минут или часов, вы можете перевести её в число с помощью функции toUInt32, затем округлить число с помощью функции intDiv и умножения, а затем перевести обратно, с помощью функции toDateTime.
## toStartOfHour
......
......@@ -277,6 +277,7 @@ public:
inline time_t toStartOfMinute(time_t t) const { return t / 60 * 60; }
inline time_t toStartOfFiveMinute(time_t t) const { return t / 300 * 300; }
inline time_t toStartOfFifteenMinutes(time_t t) const { return t / 900 * 900; }
inline time_t toStartOfHour(time_t t) const
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册