mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 01:00:48 +00:00
Better declaration and lifetime parser
This commit is contained in:
parent
5f81f47637
commit
db20681207
@ -17,8 +17,24 @@ namespace DB
|
|||||||
|
|
||||||
bool ParserDictionaryLifetime::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
bool ParserDictionaryLifetime::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
{
|
{
|
||||||
|
ParserLiteral literal_p;
|
||||||
ParserKeyValuePairsList key_value_pairs_p;
|
ParserKeyValuePairsList key_value_pairs_p;
|
||||||
ASTPtr ast_lifetime;
|
ASTPtr ast_lifetime;
|
||||||
|
auto res = std::make_shared<ASTDictionaryLifetime>();
|
||||||
|
|
||||||
|
/// simple lifetime with only maximum value e.g. LIFETIME(300)
|
||||||
|
if (literal_p.parse(pos, ast_lifetime, expected))
|
||||||
|
{
|
||||||
|
auto literal = ast_lifetime->as<const ASTLiteral &>();
|
||||||
|
|
||||||
|
if (literal.value.getType() != Field::Types::UInt64)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
res->max_sec = literal.value.get<UInt64>();
|
||||||
|
node = res;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!key_value_pairs_p.parse(pos, ast_lifetime, expected))
|
if (!key_value_pairs_p.parse(pos, ast_lifetime, expected))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -26,7 +42,7 @@ bool ParserDictionaryLifetime::parseImpl(Pos & pos, ASTPtr & node, Expected & ex
|
|||||||
if (expr_list.children.size() != 2)
|
if (expr_list.children.size() != 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto res = std::make_shared<ASTDictionaryLifetime>();
|
bool initialized_max = false;
|
||||||
for (const auto & elem : expr_list.children)
|
for (const auto & elem : expr_list.children)
|
||||||
{
|
{
|
||||||
const ASTPair & pair = elem->as<const ASTPair &>();
|
const ASTPair & pair = elem->as<const ASTPair &>();
|
||||||
@ -40,12 +56,15 @@ bool ParserDictionaryLifetime::parseImpl(Pos & pos, ASTPtr & node, Expected & ex
|
|||||||
if (pair.first == "min")
|
if (pair.first == "min")
|
||||||
res->min_sec = literal->value.get<UInt64>();
|
res->min_sec = literal->value.get<UInt64>();
|
||||||
else if (pair.first == "max")
|
else if (pair.first == "max")
|
||||||
|
{
|
||||||
res->max_sec = literal->value.get<UInt64>();
|
res->max_sec = literal->value.get<UInt64>();
|
||||||
|
initialized_max = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res->max_sec || !res->min_sec)
|
if (!initialized_max)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
node = res;
|
node = res;
|
||||||
|
@ -34,34 +34,46 @@ bool ParserDictionaryAttributeDeclaration::parseImpl(Pos & pos, ASTPtr & node, E
|
|||||||
bool injective = false;
|
bool injective = false;
|
||||||
bool is_object_id = false;
|
bool is_object_id = false;
|
||||||
|
|
||||||
/// TODO(alesapin) Loop here to avoid strict order
|
if (!type_parser.parse(pos, type, expected))
|
||||||
if (!s_default.check_without_moving(pos, expected) &&
|
return false;
|
||||||
!s_expression.check_without_moving(pos, expected) &&
|
|
||||||
!s_hierarchical.check_without_moving(pos, expected) &&
|
while(true)
|
||||||
!s_injective.check_without_moving(pos, expected) &&
|
|
||||||
!s_is_object_id.check_without_moving(pos, expected))
|
|
||||||
{
|
{
|
||||||
if (!type_parser.parse(pos, type, expected))
|
if (!default_value && s_default.ignore(pos, expected))
|
||||||
return false;
|
{
|
||||||
|
if (!default_parser.parse(pos, default_value, expected))
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expression && s_expression.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!expression_parser.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hierarchical && s_hierarchical.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
hierarchical = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!injective && s_injective.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
injective = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_object_id && s_is_object_id.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
is_object_id = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_default.ignore(pos, expected))
|
|
||||||
if (!default_parser.parse(pos, default_value, expected))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (s_expression.ignore(pos, expected))
|
|
||||||
if (!expression_parser.parse(pos, expression, expected))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (s_hierarchical.ignore(pos, expected))
|
|
||||||
hierarchical = true;
|
|
||||||
|
|
||||||
if (s_injective.ignore(pos, expected))
|
|
||||||
injective = true;
|
|
||||||
|
|
||||||
if (s_is_object_id.ignore(pos, expected))
|
|
||||||
is_object_id = true;
|
|
||||||
|
|
||||||
auto attribute_declaration = std::make_shared<ASTDictionaryAttributeDeclaration>();
|
auto attribute_declaration = std::make_shared<ASTDictionaryAttributeDeclaration>();
|
||||||
node = attribute_declaration;
|
node = attribute_declaration;
|
||||||
tryGetIdentifierNameInto(name, attribute_declaration->name);
|
tryGetIdentifierNameInto(name, attribute_declaration->name);
|
||||||
|
@ -166,10 +166,62 @@ TEST(ParserCreateDictionary, AttributesWithMultipleProperties)
|
|||||||
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->is_object_id, false);
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->is_object_id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ParserCreateDictionary, CustomAttributePropertiesOrder)
|
||||||
|
{
|
||||||
|
String input = " CREATE DICTIONARY dict3"
|
||||||
|
" ("
|
||||||
|
" key_column UInt64 IS_OBJECT_ID DEFAULT 100,"
|
||||||
|
" second_column UInt8 INJECTIVE HIERARCHICAL DEFAULT 1,"
|
||||||
|
" third_column UInt8 EXPRESSION rand() % 100 * 77 DEFAULT 2 INJECTIVE HIERARCHICAL"
|
||||||
|
" )"
|
||||||
|
" PRIMARY KEY key_column"
|
||||||
|
" SOURCE(CLICKHOUSE(REPLICA(HOST '127.0.0.1' PRIORITY 1)))"
|
||||||
|
" LIFETIME(300)";
|
||||||
|
|
||||||
|
ParserCreateDictionaryQuery parser;
|
||||||
|
ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0);
|
||||||
|
ASTCreateQuery * create = ast->as<ASTCreateQuery>();
|
||||||
|
|
||||||
|
/// test attributes
|
||||||
|
EXPECT_NE(create->dictionary_attributes_list, nullptr);
|
||||||
|
|
||||||
|
auto attributes_children = create->dictionary_attributes_list->children;
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->name, "key_column");
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->name, "second_column");
|
||||||
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->name, "third_column");
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->default_value->as<ASTLiteral>()->value.get<UInt64>(), 100);
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->default_value->as<ASTLiteral>()->value.get<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->default_value->as<ASTLiteral>()->value.get<UInt64>(), 2);
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->expression, nullptr);
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->expression, nullptr);
|
||||||
|
EXPECT_EQ(serializeAST(*attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->expression, true), "(rand() % 100) * 77");
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->hierarchical, false);
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->hierarchical, true);
|
||||||
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->hierarchical, true);
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->injective, false);
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->injective, true);
|
||||||
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->injective, true);
|
||||||
|
|
||||||
|
EXPECT_EQ(attributes_children[0]->as<ASTDictionaryAttributeDeclaration>()->is_object_id, true);
|
||||||
|
EXPECT_EQ(attributes_children[1]->as<ASTDictionaryAttributeDeclaration>()->is_object_id, false);
|
||||||
|
EXPECT_EQ(attributes_children[2]->as<ASTDictionaryAttributeDeclaration>()->is_object_id, false);
|
||||||
|
|
||||||
|
/// lifetime test
|
||||||
|
auto lifetime = create->dictionary->lifetime;
|
||||||
|
|
||||||
|
EXPECT_EQ(lifetime->min_sec, 0);
|
||||||
|
EXPECT_EQ(lifetime->max_sec, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(ParserCreateDictionary, NestedSource)
|
TEST(ParserCreateDictionary, NestedSource)
|
||||||
{
|
{
|
||||||
String input = " CREATE DICTIONARY dict3"
|
String input = " CREATE DICTIONARY dict4"
|
||||||
" ("
|
" ("
|
||||||
" key_column UInt64,"
|
" key_column UInt64,"
|
||||||
" second_column UInt8,"
|
" second_column UInt8,"
|
||||||
@ -184,7 +236,7 @@ TEST(ParserCreateDictionary, NestedSource)
|
|||||||
ParserCreateDictionaryQuery parser;
|
ParserCreateDictionaryQuery parser;
|
||||||
ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0);
|
ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0);
|
||||||
ASTCreateQuery * create = ast->as<ASTCreateQuery>();
|
ASTCreateQuery * create = ast->as<ASTCreateQuery>();
|
||||||
EXPECT_EQ(create->table, "dict3");
|
EXPECT_EQ(create->table, "dict4");
|
||||||
EXPECT_EQ(create->database, "");
|
EXPECT_EQ(create->database, "");
|
||||||
|
|
||||||
/// source test
|
/// source test
|
||||||
@ -212,3 +264,27 @@ TEST(ParserCreateDictionary, NestedSource)
|
|||||||
EXPECT_EQ(children[4]->as<ASTPair>()->first, "password");
|
EXPECT_EQ(children[4]->as<ASTPair>()->first, "password");
|
||||||
EXPECT_EQ(children[4]->as<ASTPair>()->second->as<ASTLiteral>()->value.get<String>(), "");
|
EXPECT_EQ(children[4]->as<ASTPair>()->second->as<ASTLiteral>()->value.get<String>(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST(ParserCreateDictionary, Formatting)
|
||||||
|
{
|
||||||
|
String input = " CREATE DICTIONARY test.dict5"
|
||||||
|
" ("
|
||||||
|
" key_column1 UInt64 DEFAULT 1 HIERARCHICAL INJECTIVE,"
|
||||||
|
" key_column2 String DEFAULT '',"
|
||||||
|
" second_column UInt8 EXPRESSION intDiv(50, rand() % 1000),"
|
||||||
|
" third_column UInt8"
|
||||||
|
" )"
|
||||||
|
" PRIMARY KEY key_column1, key_column2"
|
||||||
|
" SOURCE(MYSQL(HOST 'localhost' PORT 9000 USER 'default' REPLICA(HOST '127.0.0.1' PRIORITY 1) PASSWORD ''))"
|
||||||
|
" LAYOUT(CACHE(size_in_cells 50))"
|
||||||
|
" LIFETIME(MIN 1 MAX 10)"
|
||||||
|
" RANGE(MIN second_column MAX third_column)";
|
||||||
|
|
||||||
|
ParserCreateDictionaryQuery parser;
|
||||||
|
ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0);
|
||||||
|
ASTCreateQuery * create = ast->as<ASTCreateQuery>();
|
||||||
|
auto str = serializeAST(*create, true);
|
||||||
|
EXPECT_EQ(str, "CREATE DICTIONARY test.dict5 (`key_column1` UInt64 DEFAULT 1 HIERARCHICAL INJECTIVE, `key_column2` String DEFAULT '', `second_column` UInt8 EXPRESSION intDiv(50, rand() % 1000), `third_column` UInt8) PRIMARY KEY key_column1, key_column2 MYSQL(HOST 'localhost' PORT 9000 USER 'default' REPLICA (HOST '127.0.0.1' PRIORITY 1) PASSWORD '') LIFETIME(MIN 1, MAX 10) LAYOUT(CACHE(SIZE_IN_CELLS 50)) RANGE(MIN second_column, MAX third_column)");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user