TEST_F(BinderCorrectnessTest, DeleteStatementTest) { SetupTables(); auto& parser = parser::PostgresParser::GetInstance(); catalog::Catalog* catalog_ptr = catalog::Catalog::GetInstance(); oid_t db_oid = catalog_ptr->GetDatabaseWithName(DEFAULT_DB_NAME)->GetOid(); oid_t tableB_oid = catalog_ptr->GetTableWithName(DEFAULT_DB_NAME, "b")->GetOid(); string deleteSQL = "DELETE FROM b WHERE 1 = b1 AND b2 = 'str'"; unique_ptr<binder::BindNodeVisitor> binder(new binder::BindNodeVisitor()); auto parse_tree = parser.BuildParseTree(deleteSQL); auto deleteStmt = dynamic_cast<parser::DeleteStatement*>(parse_tree->GetStatements().at(0)); binder->BindNameToNode(deleteStmt); LOG_INFO("Checking first condition in where clause"); auto tupleExpr = (expression::TupleValueExpression*)deleteStmt->expr->GetChild(0) ->GetChild(1); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 0)); LOG_INFO("Checking second condition in where clause"); tupleExpr = (expression::TupleValueExpression*)deleteStmt->expr->GetChild(1) ->GetChild(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 1)); // Delete the test database auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog_ptr->DropDatabaseWithName(DEFAULT_DB_NAME, txn); txn_manager.CommitTransaction(txn); }
std::shared_ptr<Statement> TrafficCop::PrepareStatement( const std::string &statement_name, const std::string &query_string, UNUSED_ATTRIBUTE std::string &error_message) { LOG_TRACE("Prepare Statement name: %s", statement_name.c_str()); LOG_TRACE("Prepare Statement query: %s", query_string.c_str()); std::shared_ptr<Statement> statement( new Statement(statement_name, query_string)); try { auto &peloton_parser = parser::Parser::GetInstance(); auto sql_stmt = peloton_parser.BuildParseTree(query_string); if (sql_stmt->is_valid == false) { throw ParserException("Error parsing SQL statement"); } auto plan = optimizer_->BuildPelotonPlanTree(sql_stmt); statement->SetPlanTree(plan); // Get the tables that our plan references so that we know how to // invalidate it at a later point when the catalog changes const std::set<oid_t> table_oids = planner::PlanUtil::GetTablesReferenced(plan.get()); statement->SetReferencedTables(table_oids); for (auto stmt : sql_stmt->GetStatements()) { LOG_TRACE("SQLStatement: %s", stmt->GetInfo().c_str()); if (stmt->GetType() == StatementType::SELECT) { auto tuple_descriptor = GenerateTupleDescriptor(stmt); statement->SetTupleDescriptor(tuple_descriptor); } break; } #ifdef LOG_DEBUG_ENABLED if (statement->GetPlanTree().get() != nullptr) { LOG_DEBUG("Statement Prepared: %s", statement->GetInfo().c_str()); LOG_TRACE("%s", statement->GetPlanTree().get()->GetInfo().c_str()); } #endif return std::move(statement); } catch (Exception &e) { error_message = e.what(); return nullptr; } }
status_t BnChatSession::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t result = 0x80000000; _TRACE("ChatSession::onTransact[pid:%d] >>:code 0x%x",GetCallerPID(),code); //data.print(); switch(code) { case ICS_getName: { CHECK_INTERFACE(IChatSession, data, reply); //CHECKOUT_CALLER(data); String16 name = const_cast<BnChatSession*>(this)->GetName(); reply->writeString16(name); result = NO_ERROR; } break; case ICS_GetStatements: { CHECK_INTERFACE(IChatSession, data, reply); //CHECKOUT_CALLER(data); Vector<String16> list = GetStatements(); const size_t N = list.size(); reply->writeInt32(N); _TRACE("GetStatements num %u",(unsigned int)N); for (size_t i=0; i<N; i++) { reply->writeString16(list[i]); } result = NO_ERROR; } break; case ICS_Say: { CHECK_INTERFACE(IChatSession, data, reply); //CHECKOUT_CALLER(data); String16 statement = data.readString16(); status_t err = Say(statement); reply->writeInt32(err); result = NO_ERROR; } break; case ICS_AsyncSay: { CHECK_INTERFACE(IChatSession, data, reply); //CHECKOUT_CALLER(data); String16 statement = data.readString16(); AsyncSay(statement); result = NO_ERROR; } break; case ICS_Advise: { CHECK_INTERFACE(IChatSession, data, reply); sp<IChatSessionEvents> eventSink = interface_cast<IChatSessionEvents>(data.readStrongBinder()); Advise(eventSink); result = NO_ERROR; } break; case ICS_Unadvise: { CHECK_INTERFACE(IChatSession, data, reply); //CHECKOUT_CALLER(data); status_t err = Unadvise(); reply->writeInt32(err); result = NO_ERROR; } break; default: result = BBinder::onTransact(code, data, reply, flags); } _TRACE("ChatSession::onTransact[pid:%d] <<:result %d",GetCallerPID(),result); //reply.print(); return result; }
TEST_F(BinderCorrectnessTest, SelectStatementTest) { SetupTables(); auto& parser = parser::PostgresParser::GetInstance(); catalog::Catalog* catalog_ptr = catalog::Catalog::GetInstance(); // Test regular table name LOG_INFO("Parsing sql query"); unique_ptr<binder::BindNodeVisitor> binder(new binder::BindNodeVisitor()); string selectSQL = "SELECT A.a1, B.b2 FROM A INNER JOIN b ON a.a1 = b.b1 " "WHERE a1 < 100 GROUP BY A.a1, B.b2 HAVING a1 > 50 " "ORDER BY a1"; auto parse_tree = parser.BuildParseTree(selectSQL); auto selectStmt = dynamic_cast<parser::SelectStatement*>(parse_tree->GetStatements().at(0)); binder->BindNameToNode(selectStmt); oid_t db_oid = catalog_ptr->GetDatabaseWithName(DEFAULT_DB_NAME)->GetOid(); oid_t tableA_oid = catalog_ptr->GetTableWithName(DEFAULT_DB_NAME, "a")->GetOid(); oid_t tableB_oid = catalog_ptr->GetTableWithName(DEFAULT_DB_NAME, "b")->GetOid(); // Check select_list LOG_INFO("Checking select list"); auto tupleExpr = (expression::TupleValueExpression*)(*selectStmt->select_list)[0]; EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // A.a1 EXPECT_EQ(type::TypeId::INTEGER, tupleExpr->GetValueType()); tupleExpr = (expression::TupleValueExpression*)(*selectStmt->select_list)[1]; EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 1)); // B.b2 EXPECT_EQ(type::TypeId::VARCHAR, tupleExpr->GetValueType()); // Check join condition LOG_INFO("Checking join condition"); tupleExpr = (expression::TupleValueExpression*) selectStmt->from_table->join->condition->GetChild(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // a.a1 tupleExpr = (expression::TupleValueExpression*) selectStmt->from_table->join->condition->GetChild(1); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 0)); // b.b1 // Check Where clause LOG_INFO("Checking where clause"); tupleExpr = (expression::TupleValueExpression*)selectStmt->where_clause->GetChild(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // a1 // Check Group By and Having LOG_INFO("Checking group by"); tupleExpr = (expression::TupleValueExpression*)selectStmt->group_by->columns->at(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // A.a1 tupleExpr = (expression::TupleValueExpression*)selectStmt->group_by->columns->at(1); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 1)); // B.b2 tupleExpr = (expression::TupleValueExpression*)selectStmt->group_by->having->GetChild( 0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // a1 // Check Order By LOG_INFO("Checking order by"); tupleExpr = (expression::TupleValueExpression*)selectStmt->order->exprs->at(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // a1 // Check alias ambiguous LOG_INFO("Checking duplicate alias and table name."); binder.reset(new binder::BindNodeVisitor()); selectSQL = "SELECT * FROM A, B as A"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = (parser::SelectStatement*)(parse_tree->GetStatements().at(0)); try { binder->BindNameToNode(selectStmt); EXPECT_TRUE(false); } catch (Exception& e) { LOG_INFO("Correct! Exception(%s) catched", e.what()); } // Test select from different table instances from the same physical schema binder.reset(new binder::BindNodeVisitor()); selectSQL = "SELECT * FROM A, A as AA where A.a1 = AA.a2"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = (parser::SelectStatement*)(parse_tree->GetStatements().at(0)); binder->BindNameToNode(selectStmt); LOG_INFO("Checking where clause"); tupleExpr = (expression::TupleValueExpression*)selectStmt->where_clause->GetChild(0); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); // a1 tupleExpr = (expression::TupleValueExpression*)selectStmt->where_clause->GetChild(1); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 1)); // a1 // Test alias and select_list LOG_INFO("Checking select_list and table alias binding"); binder.reset(new binder::BindNodeVisitor()); selectSQL = "SELECT AA.a1, b2 FROM A as AA, B WHERE AA.a1 = B.b1"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = (parser::SelectStatement*)(parse_tree->GetStatements().at(0)); binder->BindNameToNode(selectStmt); tupleExpr = (expression::TupleValueExpression*)(selectStmt->select_list->at(0)); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableA_oid, 0)); tupleExpr = (expression::TupleValueExpression*)(selectStmt->select_list->at(1)); EXPECT_EQ(tupleExpr->GetBoundOid(), make_tuple(db_oid, tableB_oid, 1)); // Delete the test database auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog_ptr->DropDatabaseWithName(DEFAULT_DB_NAME, txn); txn_manager.CommitTransaction(txn); }