Skip to content

Commit

Permalink
Extend parser CREATE INDEX (cmu-db#376)
Browse files Browse the repository at this point in the history
* Parse the expression in CREATE INDEX, with tests. Note that the Postgres parser's node either comes with a name or an expression, not both.

* Doxygen.
  • Loading branch information
lmwnshn authored and apavlo committed May 17, 2019
1 parent c1c3979 commit be93dca
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
42 changes: 39 additions & 3 deletions src/include/parser/create_statement.h
Expand Up @@ -325,6 +325,42 @@ struct ColumnDefinition {
const FKConstrMatchType fk_match_type_ = FKConstrMatchType::SIMPLE;
};

/**
* Represents an index attribute.
*/
class IndexAttr {
public:
/**
* Create an index attribute on a column name.
*/
explicit IndexAttr(std::string name) : name_(std::move(name)), expr_(nullptr) {}

/**
* Create an index attribute on an expression.
*/
explicit IndexAttr(std::shared_ptr<AbstractExpression> expr) : name_(""), expr_(std::move(expr)) {}

/**
* @return the name of the column that we're indexed on
*/
std::string GetName() const {
TERRIER_ASSERT(expr_ == nullptr, "Expressions don't come with names.");
return name_;
}

/**
* @return the expression that we're indexed on
*/
std::shared_ptr<AbstractExpression> GetExpression() const {
TERRIER_ASSERT(expr_ != nullptr, "Names don't come with expressions.");
return expr_;
}

private:
const std::string name_;
const std::shared_ptr<AbstractExpression> expr_;
};

/**
* Represents the sql "CREATE ..."
*/
Expand Down Expand Up @@ -360,7 +396,7 @@ class CreateStatement : public TableRefStatement {
* @param index_attrs index attributes
*/
CreateStatement(std::shared_ptr<TableInfo> table_info, IndexType index_type, bool unique, std::string index_name,
std::vector<std::string> index_attrs)
std::vector<IndexAttr> index_attrs)
: TableRefStatement(StatementType::CREATE, std::move(table_info)),
create_type_(kIndex),
index_type_(index_type),
Expand Down Expand Up @@ -449,7 +485,7 @@ class CreateStatement : public TableRefStatement {
/**
* @return index attributes for [CREATE INDEX]
*/
std::vector<std::string> GetIndexAttributes() { return index_attrs_; }
std::vector<IndexAttr> GetIndexAttributes() { return index_attrs_; }

/**
* @return true if "IF NOT EXISTS" for [CREATE SCHEMA], false otherwise
Expand Down Expand Up @@ -508,7 +544,7 @@ class CreateStatement : public TableRefStatement {
const IndexType index_type_ = IndexType::INVALID;
const bool unique_index_ = false;
const std::string index_name_;
const std::vector<std::string> index_attrs_;
const std::vector<IndexAttr> index_attrs_;

// CREATE SCHEMA
const bool if_not_exists_ = false;
Expand Down
3 changes: 2 additions & 1 deletion src/include/planner/plannodes/create_index_plan_node.h
Expand Up @@ -101,7 +101,8 @@ class CreateIndexPlanNode : public AbstractPlanNode {
std::vector<std::string> index_attrs_holder;

for (auto &attr : create_stmt->GetIndexAttributes()) {
index_attrs_holder.push_back(attr);
// TODO(WAN/WEN): Wen, all yours. Note that it either has a name or an expression, not both.
index_attrs_holder.push_back(attr.GetName());
}

index_attrs_ = index_attrs_holder;
Expand Down
10 changes: 7 additions & 3 deletions src/parser/postgresparser.cpp
Expand Up @@ -1263,10 +1263,14 @@ std::unique_ptr<SQLStatement> PostgresParser::CreateIndexTransform(IndexStmt *ro
auto unique = root->unique;
auto index_name = root->idxname;

std::vector<std::string> index_attrs;
std::vector<IndexAttr> index_attrs;
for (auto cell = root->indexParams->head; cell != nullptr; cell = cell->next) {
std::string index_attr = reinterpret_cast<IndexElem *>(cell->data.ptr_value)->name;
index_attrs.emplace_back(index_attr);
auto *index_elem = reinterpret_cast<IndexElem *>(cell->data.ptr_value);
if (index_elem->expr == nullptr) {
index_attrs.emplace_back(index_elem->name);
} else {
index_attrs.emplace_back(ExprTransform(index_elem->expr));
}
}

auto table_name = root->relation->relname == nullptr ? "" : root->relation->relname;
Expand Down
32 changes: 30 additions & 2 deletions test/parser/parser_test.cpp
Expand Up @@ -173,6 +173,34 @@ TEST_F(ParserTestBase, CreateFunctionTest) {
EXPECT_EQ(func_params[0]->GetDataType(), BaseFunctionParameter::DataType::BOOL);
}

// NOLINTNEXTLINE
TEST_F(ParserTestBase, CreateIndexTest) {
std::string query = "CREATE INDEX IDX_ORDER ON oorder ((O_W_ID - 2), (O + W + O));";
auto stmt_list = pgparser.BuildParseTree(query);
auto create_stmt = reinterpret_cast<CreateStatement *>(stmt_list[0].get());

EXPECT_EQ(create_stmt->GetCreateType(), CreateStatement::kIndex);
EXPECT_EQ(create_stmt->GetIndexName(), "idx_order");
EXPECT_EQ(create_stmt->GetTableName(), "oorder");
EXPECT_EQ(create_stmt->GetIndexAttributes().size(), 2);
auto ia1 = create_stmt->GetIndexAttributes()[0].GetExpression();
EXPECT_EQ(ia1->GetExpressionType(), ExpressionType::OPERATOR_MINUS);
auto ia1l = reinterpret_cast<TupleValueExpression *>(ia1->GetChild(0).get());
EXPECT_EQ(ia1l->GetColumnName(), "o_w_id");
auto ia1r = reinterpret_cast<ConstantValueExpression *>(ia1->GetChild(1).get());
EXPECT_EQ(type::TransientValuePeeker::PeekInteger(ia1r->GetValue()), 2);
auto ia2 = create_stmt->GetIndexAttributes()[1].GetExpression();
EXPECT_EQ(ia2->GetExpressionType(), ExpressionType::OPERATOR_PLUS);
auto ia2l = reinterpret_cast<TupleValueExpression *>(ia2->GetChild(0).get());
EXPECT_EQ(ia2l->GetExpressionType(), ExpressionType::OPERATOR_PLUS);
auto ia2ll = reinterpret_cast<TupleValueExpression *>(ia2l->GetChild(0).get());
auto ia2lr = reinterpret_cast<TupleValueExpression *>(ia2l->GetChild(1).get());
auto ia2r = reinterpret_cast<TupleValueExpression *>(ia2->GetChild(1).get());
EXPECT_EQ(ia2ll->GetColumnName(), "o");
EXPECT_EQ(ia2lr->GetColumnName(), "w");
EXPECT_EQ(ia2r->GetColumnName(), "o");
}

// NOLINTNEXTLINE
TEST_F(ParserTestBase, CreateTableTest) {
std::string query =
Expand Down Expand Up @@ -1226,8 +1254,8 @@ TEST_F(ParserTestBase, OldCreateIndexTest) {
EXPECT_TRUE(create_stmt->IsUniqueIndex());
EXPECT_EQ(create_stmt->GetIndexName(), "idx_order");
EXPECT_EQ(create_stmt->GetTableName(), "oorder");
EXPECT_EQ(create_stmt->GetIndexAttributes()[0], "o_w_id");
EXPECT_EQ(create_stmt->GetIndexAttributes()[1], "o_d_id");
EXPECT_EQ(create_stmt->GetIndexAttributes()[0].GetName(), "o_w_id");
EXPECT_EQ(create_stmt->GetIndexAttributes()[1].GetName(), "o_d_id");

query = "CREATE INDEX ii ON t USING SKIPLIST (col);";
stmt_list = pgparser.BuildParseTree(query);
Expand Down

0 comments on commit be93dca

Please sign in to comment.