Skip to content

Commit

Permalink
Merge pull request #35 from project-tsurugi/wip/drop-if-exists
Browse files Browse the repository at this point in the history
fix: ensure parse DROP ... IF EXISTS.
  • Loading branch information
ashigeru authored Nov 14, 2023
2 parents dce9f1f + f8c5832 commit b2cd34f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 4 deletions.
12 changes: 10 additions & 2 deletions parser/src/grammar/SqlParserRules.g4
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,20 @@ indexElement

// drop table
dropTableStatement
: K_DROP K_TABLE name
: K_DROP K_TABLE ( dropTableOption )? name
;

dropTableOption
: K_IF K_EXISTS
;

// drop index
dropIndexStatement
: K_DROP K_INDEX name
: K_DROP K_INDEX ( dropIndexOption )? name
;

dropIndexOption
: K_IF K_EXISTS
;

// general statement
Expand Down
27 changes: 27 additions & 0 deletions parser/src/impl/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,25 +1140,52 @@ std::unique_ptr<model::statement::Statement> Engine::visit(Grammar::DropTableSta
auto n = c->name();
if (is_defined(c->K_DROP()) && is_defined(c->K_TABLE()) && is_defined(n)) {
auto result = f.DropTableStatement() << region(c);
if (auto a = c->dropTableOption(); is_defined(a)) {
visit(a, result.get());
}
auto name = visit(n);
result->table(std::move(name));
return result;
}
rule_error(c);
}

void Engine::visit(Grammar::DropTableOptionContext *c, model::statement::ddl::DropTableStatement *r) {
check(c);
check(c);
using Attribute = model::statement::ddl::DropTableStatement::Attribute;
if (is_defined(c->K_IF()) && is_defined(c->K_EXISTS())) {
r->attributes().emplace(Attribute::IF_EXISTS);
return;
}
rule_error(c);
}

std::unique_ptr<model::statement::Statement> Engine::visit(Grammar::DropIndexStatementContext *c) {
check(c);
auto n = c->name();
if (is_defined(c->K_DROP()) && is_defined(c->K_INDEX()) && is_defined(n)) {
auto result = f.DropIndexStatement() << region(c);
if (auto a = c->dropIndexOption(); is_defined(a)) {
visit(a, result.get());
}
auto name = visit(n);
result->index(std::move(name));
return result;
}
rule_error(c);
}

void Engine::visit(Grammar::DropIndexOptionContext *c, model::statement::ddl::DropIndexStatement *r) {
check(c);
using Attribute = model::statement::ddl::DropIndexStatement::Attribute;
if (is_defined(c->K_IF()) && is_defined(c->K_EXISTS())) {
r->attributes().emplace(Attribute::IF_EXISTS);
return;
}
rule_error(c);
}

std::unique_ptr<model::statement::Statement> Engine::visit(Grammar::StatementContext *c) {
check(c);
if (auto s = c->expressionStatement(); is_defined(s)) {
Expand Down
15 changes: 13 additions & 2 deletions parser/src/impl/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,16 +462,27 @@ class Engine {

// -- DROP TABLE
// dropTableStatement
// : K_DROP K_TABLE name
// : K_DROP K_TABLE ( dropTableOption )? name
// ;
std::unique_ptr<model::statement::Statement> visit(Grammar::DropTableStatementContext *);

// dropTableOption
// : K_IF K_EXISTS
// ;
void visit(Grammar::DropTableOptionContext *, model::statement::ddl::DropTableStatement *);


// -- DROP INDEX
// dropIndexStatement
// : K_DROP K_INDEX name
// : K_DROP K_INDEX ( dropIndexOption )? name
// ;
std::unique_ptr<model::statement::Statement> visit(Grammar::DropIndexStatementContext *);

// dropTableOption
// : K_IF K_EXISTS
// ;
void visit(Grammar::DropIndexOptionContext *, model::statement::ddl::DropIndexStatement *);

// -- generic statements
// statement
// : expressionStatement
Expand Down
12 changes: 12 additions & 0 deletions parser/test/ParserDropIndexTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,23 @@ class ParserDropIndexTest : public ParserTestBase, public ::testing::Test {
}
};

template<typename C, typename E>
static bool contains(const C& container, const E& element) {
return container.find(element) != container.end();
}


TEST_F(ParserDropIndexTest, simple) {
auto stmt = parse("DROP INDEX t");

EXPECT_TRUE(equals(f.Name("t"), stmt->index()));
}

TEST_F(ParserDropIndexTest, if_exists) {
auto stmt = parse("DROP INDEX IF EXISTS t");

EXPECT_TRUE(equals(f.Name("t"), stmt->index()));
EXPECT_TRUE(contains(stmt->attributes(), DropIndexStatement::Attribute::IF_EXISTS));
}

} // namespace shakujo::parser
12 changes: 12 additions & 0 deletions parser/test/ParserDropTableTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,23 @@ class ParserDropTableTest : public ParserTestBase, public ::testing::Test {
}
};

template<typename C, typename E>
static bool contains(const C& container, const E& element) {
return container.find(element) != container.end();
}

TEST_F(ParserDropTableTest, simple) {
auto stmt = parse("DROP TABLE t");

EXPECT_TRUE(equals(f.Name("t"), stmt->table()));
EXPECT_FALSE(contains(stmt->attributes(), DropTableStatement::Attribute::IF_EXISTS));
}

TEST_F(ParserDropTableTest, if_exists) {
auto stmt = parse("DROP TABLE IF EXISTS t");

EXPECT_TRUE(equals(f.Name("t"), stmt->table()));
EXPECT_TRUE(contains(stmt->attributes(), DropTableStatement::Attribute::IF_EXISTS));
}

} // namespace shakujo::parser

0 comments on commit b2cd34f

Please sign in to comment.