Merge pull request #35706 from yakov-olkhovskiy/ephemeral-35641

Allow EPHEMERAL without explicit default expression
This commit is contained in:
Yakov Olkhovskiy 2022-04-01 10:49:29 -04:00 committed by GitHub
commit 38993f215f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 10 deletions

View File

@ -114,9 +114,9 @@ In addition, this column is not substituted when using an asterisk in a SELECT q
### EPHEMERAL {#ephemeral} ### EPHEMERAL {#ephemeral}
`EPHEMERAL expr` `EPHEMERAL [expr]`
Ephemeral column. Such a column isn't stored in the table and cannot be SELECTed, but can be referenced in the defaults of CREATE statement. Ephemeral column. Such a column isn't stored in the table and cannot be SELECTed, but can be referenced in the defaults of CREATE statement. If `expr` is omitted type for column is required.
INSERT without list of columns will skip such column, so SELECT/INSERT invariant is preserved - the dump obtained using `SELECT *` can be inserted back into the table using INSERT without specifying the list of columns. INSERT without list of columns will skip such column, so SELECT/INSERT invariant is preserved - the dump obtained using `SELECT *` can be inserted back into the table using INSERT without specifying the list of columns.
### ALIAS {#alias} ### ALIAS {#alias}

View File

@ -110,9 +110,9 @@ SELECT x, toTypeName(x) FROM t1;
### EPHEMERAL {#ephemeral} ### EPHEMERAL {#ephemeral}
`EPHEMERAL expr` `EPHEMERAL [expr]`
Эфемерное выражение. Такой столбец не хранится в таблице и не может быть получен в запросе SELECT, но на него можно ссылаться в выражениях по умолчанию запроса CREATE. Эфемерное выражение. Такой столбец не хранится в таблице и не может быть получен в запросе SELECT, но на него можно ссылаться в выражениях по умолчанию запроса CREATE. Если значение по умолчанию `expr` не указано, то тип колонки должен быть специфицирован.
INSERT без списка столбцов игнорирует этот столбец, таким образом сохраняется инвариант - т.е. дамп, полученный путём `SELECT *`, можно вставить обратно в таблицу INSERT-ом без указания списка столбцов. INSERT без списка столбцов игнорирует этот столбец, таким образом сохраняется инвариант - т.е. дамп, полученный путём `SELECT *`, можно вставить обратно в таблицу INSERT-ом без указания списка столбцов.
### ALIAS {#alias} ### ALIAS {#alias}

View File

@ -508,7 +508,9 @@ ColumnsDescription InterpreterCreateQuery::getColumnsDescription(
default_expr_list->children.emplace_back( default_expr_list->children.emplace_back(
setAlias( setAlias(
col_decl.default_expression->clone(), col_decl.default_specifier == "EPHEMERAL" ? /// can be ASTLiteral::value NULL
std::make_shared<ASTLiteral>(data_type_ptr->getDefault()) :
col_decl.default_expression->clone(),
tmp_column_name)); tmp_column_name));
} }
else else
@ -536,7 +538,11 @@ ColumnsDescription InterpreterCreateQuery::getColumnsDescription(
if (col_decl.default_expression) if (col_decl.default_expression)
{ {
ASTPtr default_expr = col_decl.default_expression->clone(); ASTPtr default_expr =
col_decl.default_specifier == "EPHEMERAL" && col_decl.default_expression->as<ASTLiteral>()->value.isNull() ?
std::make_shared<ASTLiteral>(DataTypeFactory::instance().get(col_decl.type)->getDefault()) :
col_decl.default_expression->clone();
if (col_decl.type) if (col_decl.type)
column.type = name_type_it->type; column.type = name_type_it->type;
else else

View File

@ -1,6 +1,7 @@
#include <Parsers/ASTColumnDeclaration.h> #include <Parsers/ASTColumnDeclaration.h>
#include <Common/quoteString.h> #include <Common/quoteString.h>
#include <IO/Operators.h> #include <IO/Operators.h>
#include <Parsers/ASTLiteral.h>
namespace DB namespace DB
@ -71,8 +72,12 @@ void ASTColumnDeclaration::formatImpl(const FormatSettings & settings, FormatSta
if (default_expression) if (default_expression)
{ {
settings.ostr << ' ' << (settings.hilite ? hilite_keyword : "") << default_specifier << (settings.hilite ? hilite_none : "") << ' '; settings.ostr << ' ' << (settings.hilite ? hilite_keyword : "") << default_specifier << (settings.hilite ? hilite_none : "");
default_expression->formatImpl(settings, state, frame); if (default_specifier != "EPHEMERAL" || !default_expression->as<ASTLiteral>()->value.isNull())
{
settings.ostr << ' ';
default_expression->formatImpl(settings, state, frame);
}
} }
if (comment) if (comment)

View File

@ -9,6 +9,7 @@
#include <Parsers/CommonParsers.h> #include <Parsers/CommonParsers.h>
#include <Parsers/ParserDataType.h> #include <Parsers/ParserDataType.h>
#include <Poco/String.h> #include <Poco/String.h>
#include <Parsers/ASTLiteral.h>
namespace DB namespace DB
@ -185,8 +186,7 @@ bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, ASTPtr & node, E
} }
Pos pos_before_specifier = pos; Pos pos_before_specifier = pos;
if (s_default.ignore(pos, expected) || s_materialized.ignore(pos, expected) || if (s_default.ignore(pos, expected) || s_materialized.ignore(pos, expected) || s_alias.ignore(pos, expected))
s_ephemeral.ignore(pos, expected) || s_alias.ignore(pos, expected))
{ {
default_specifier = Poco::toUpper(std::string{pos_before_specifier->begin, pos_before_specifier->end}); default_specifier = Poco::toUpper(std::string{pos_before_specifier->begin, pos_before_specifier->end});
@ -194,6 +194,12 @@ bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, ASTPtr & node, E
if (!expr_parser.parse(pos, default_expression, expected)) if (!expr_parser.parse(pos, default_expression, expected))
return false; return false;
} }
else if (s_ephemeral.ignore(pos, expected))
{
default_specifier = "EPHEMERAL";
if (!expr_parser.parse(pos, default_expression, expected) && type)
default_expression = std::make_shared<ASTLiteral>(Field());
}
if (require_type && !type && !default_expression) if (require_type && !type && !default_expression)
return false; /// reject column name without type return false; /// reject column name without type

View File

@ -6,3 +6,11 @@ z UInt32 DEFAULT 5
17 5 17 5
7 5 7 5
21 5 21 5
x UInt32 DEFAULT y
y UInt32 EPHEMERAL 0
z UInt32 DEFAULT 5
1 2
0 2
0 5
7 5
21 5

View File

@ -38,3 +38,43 @@ SELECT * FROM t_ephemeral_02205_1;
DROP TABLE IF EXISTS t_ephemeral_02205_1; DROP TABLE IF EXISTS t_ephemeral_02205_1;
# Test without default
CREATE TABLE t_ephemeral_02205_1 (x UInt32 DEFAULT y, y UInt32 EPHEMERAL, z UInt32 DEFAULT 5) ENGINE = Memory;
DESCRIBE t_ephemeral_02205_1;
# Test INSERT without columns list - should participate only ordinary columns (x, z)
INSERT INTO t_ephemeral_02205_1 VALUES (1, 2);
# SELECT * should only return ordinary columns (x, z) - ephemeral is not stored in the table
SELECT * FROM t_ephemeral_02205_1;
TRUNCATE TABLE t_ephemeral_02205_1;
INSERT INTO t_ephemeral_02205_1 VALUES (DEFAULT, 2);
SELECT * FROM t_ephemeral_02205_1;
TRUNCATE TABLE t_ephemeral_02205_1;
# Test INSERT using ephemerals default
INSERT INTO t_ephemeral_02205_1 (x, y) VALUES (DEFAULT, DEFAULT);
SELECT * FROM t_ephemeral_02205_1;
TRUNCATE TABLE t_ephemeral_02205_1;
# Test INSERT using explicit ephemerals value
INSERT INTO t_ephemeral_02205_1 (x, y) VALUES (DEFAULT, 7);
SELECT * FROM t_ephemeral_02205_1;
# Test ALTER TABLE DELETE
ALTER TABLE t_ephemeral_02205_1 DELETE WHERE x = 7;
SELECT * FROM t_ephemeral_02205_1;
TRUNCATE TABLE t_ephemeral_02205_1;
# Test INSERT into column, defaulted to ephemeral, but explicitly provided with value
INSERT INTO t_ephemeral_02205_1 (x, y) VALUES (21, 7);
SELECT * FROM t_ephemeral_02205_1;
DROP TABLE IF EXISTS t_ephemeral_02205_1;