Parser allow specify primary key in column list

This commit is contained in:
Maksim Kita 2020-10-12 16:55:41 +03:00
parent 6512d84b31
commit 9bd30b041a
6 changed files with 83 additions and 0 deletions

View File

@ -124,6 +124,8 @@ ASTPtr ASTColumns::clone() const
res->set(res->indices, indices->clone());
if (constraints)
res->set(res->constraints, constraints->clone());
if (primary_key)
res->set(res->primary_key, primary_key->clone());
return res;
}

View File

@ -41,6 +41,7 @@ public:
ASTExpressionList * columns = nullptr;
ASTExpressionList * indices = nullptr;
ASTExpressionList * constraints = nullptr;
IAST * primary_key = nullptr;
String getID(char) const override { return "Columns definition"; }

View File

@ -19,6 +19,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int BAD_ARGUMENTS;
}
bool ParserNestedTable::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ParserToken open(TokenType::OpeningRoundBracket);
@ -150,10 +155,12 @@ bool ParserTablePropertyDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expecte
{
ParserKeyword s_index("INDEX");
ParserKeyword s_constraint("CONSTRAINT");
ParserKeyword s_primary_key("PRIMARY KEY");
ParserIndexDeclaration index_p;
ParserConstraintDeclaration constraint_p;
ParserColumnDeclaration column_p{true, true};
ParserExpression primary_key_p;
ASTPtr new_node = nullptr;
@ -167,6 +174,11 @@ bool ParserTablePropertyDeclaration::parseImpl(Pos & pos, ASTPtr & node, Expecte
if (!constraint_p.parse(pos, new_node, expected))
return false;
}
else if (s_primary_key.ignore(pos, expected))
{
if (!primary_key_p.parse(pos, new_node, expected))
return false;
}
else
{
if (!column_p.parse(pos, new_node, expected))
@ -201,6 +213,7 @@ bool ParserTablePropertiesDeclarationList::parseImpl(Pos & pos, ASTPtr & node, E
ASTPtr columns = std::make_shared<ASTExpressionList>();
ASTPtr indices = std::make_shared<ASTExpressionList>();
ASTPtr constraints = std::make_shared<ASTExpressionList>();
ASTPtr primary_key;
for (const auto & elem : list->children)
{
@ -210,6 +223,14 @@ bool ParserTablePropertiesDeclarationList::parseImpl(Pos & pos, ASTPtr & node, E
indices->children.push_back(elem);
else if (elem->as<ASTConstraintDeclaration>())
constraints->children.push_back(elem);
else if (elem->as<ASTIdentifier>() || elem->as<ASTFunction>())
{
if (primary_key)
{
throw Exception("Multiple primary keys are not allowed.", ErrorCodes::BAD_ARGUMENTS);
}
primary_key = elem;
}
else
return false;
}
@ -222,6 +243,8 @@ bool ParserTablePropertiesDeclarationList::parseImpl(Pos & pos, ASTPtr & node, E
res->set(res->indices, indices);
if (!constraints->children.empty())
res->set(res->constraints, constraints);
if (primary_key)
res->set(res->primary_key, primary_key);
node = res;
@ -472,6 +495,15 @@ bool ParserCreateTableQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expe
query->set(query->columns_list, columns_list);
query->set(query->storage, storage);
if (query->storage && query->columns_list && query->columns_list->primary_key)
{
if (query->storage->primary_key)
{
throw Exception("Multiple primary keys are not allowed.", ErrorCodes::BAD_ARGUMENTS);
}
query->storage->primary_key = query->columns_list->primary_key;
}
tryGetIdentifierNameInto(as_database, query->as_database);
tryGetIdentifierNameInto(as_table, query->as_table);
query->set(query->select, select);

View File

@ -391,6 +391,7 @@ protected:
* ...
* INDEX name1 expr TYPE type1(args) GRANULARITY value,
* ...
* PRIMARY KEY expr
* ) ENGINE = engine
*
* Or:

View File

@ -0,0 +1,4 @@
1
1
1 1
1 1

View File

@ -0,0 +1,43 @@
DROP DATABASE IF EXISTS test_01516;
CREATE DATABASE test_01516 ENGINE=Ordinary; -- Full ATTACH requires UUID with Atomic
USE test_01516;
DROP TABLE IF EXISTS primary_key_test;
CREATE TABLE primary_key_test(v Int32, PRIMARY KEY(v)) ENGINE=ReplacingMergeTree ORDER BY v;
INSERT INTO primary_key_test VALUES (1), (1), (1);
DETACH TABLE primary_key_test;
ATTACH TABLE primary_key_test(v Int32, PRIMARY KEY(v)) ENGINE=ReplacingMergeTree ORDER BY v;
SELECT * FROM primary_key_test FINAL;
DROP TABLE primary_key_test;
CREATE TABLE primary_key_test(v Int32) ENGINE=ReplacingMergeTree ORDER BY v PRIMARY KEY(v);
INSERT INTO primary_key_test VALUES (1), (1), (1);
DETACH TABLE primary_key_test;
ATTACH TABLE primary_key_test(v Int32) ENGINE=ReplacingMergeTree ORDER BY v PRIMARY KEY(v);
SELECT * FROM primary_key_test FINAL;
DROP TABLE primary_key_test;
CREATE TABLE primary_key_test(v Int32, PRIMARY KEY(v), PRIMARY KEY(v)) ENGINE=ReplacingMergeTree ORDER BY v; -- { clientError 36; }
CREATE TABLE primary_key_test(v Int32, PRIMARY KEY(v)) ENGINE=ReplacingMergeTree ORDER BY v PRIMARY KEY(v); -- { clientError 36; }
CREATE TABLE primary_key_test(v1 Int32, v2 Int32, PRIMARY KEY(v1, v2)) ENGINE=ReplacingMergeTree ORDER BY (v1, v2);
INSERT INTO primary_key_test VALUES (1, 1), (1, 1), (1, 1);
DETACH TABLE primary_key_test;
ATTACH TABLE primary_key_test(v1 Int32, v2 Int32, PRIMARY KEY(v1, v2)) ENGINE=ReplacingMergeTree ORDER BY (v1, v2);
SELECT * FROM primary_key_test FINAL;
DROP TABLE primary_key_test;
CREATE TABLE primary_key_test(v1 Int32, v2 Int32) ENGINE=ReplacingMergeTree ORDER BY (v1, v2) PRIMARY KEY(v1, v2);
INSERT INTO primary_key_test VALUES (1, 1), (1, 1), (1, 1);
DETACH TABLE primary_key_test;
ATTACH TABLE primary_key_test(v1 Int32, v2 Int32) ENGINE=ReplacingMergeTree ORDER BY (v1, v2) PRIMARY KEY(v1, v2);
SELECT * FROM primary_key_test FINAL;
DROP TABLE primary_key_test;
CREATE TABLE primary_key_test(v1 Int32, v2 Int32, PRIMARY KEY(v1, v2), PRIMARY KEY(v1, v2)) ENGINE=ReplacingMergeTree ORDER BY (v1, v2); -- { clientError 36; }
CREATE TABLE primary_key_test(v1 Int32, v2 Int32, PRIMARY KEY(v1, v2)) ENGINE=ReplacingMergeTree ORDER BY (v1, v2) PRIMARY KEY(v1, v2); -- { clientError 36; }
DROP DATABASE test_01516;