bool SeqScanPlan::SerializeTo(SerializeOutput &output) { // A placeholder for the total size written at the end int start = output.Position(); output.WriteInt(-1); // Write the SeqScanPlan type PlanNodeType plan_type = GetPlanNodeType(); output.WriteByte(static_cast<int8_t>(plan_type)); // Write database id and table id if (!GetTable()) { // The plan is not completed return false; } oid_t database_id = GetTable()->GetDatabaseOid(); oid_t table_id = GetTable()->GetOid(); output.WriteInt(static_cast<int>(database_id)); output.WriteInt(static_cast<int>(table_id)); // If column has 0 item, just write the columnid_count with 0 int columnid_count = GetColumnIds().size(); output.WriteInt(columnid_count); // If column has 0 item, nothing happens here for (int it = 0; it < columnid_count; it++) { oid_t col_id = GetColumnIds()[it]; output.WriteInt(static_cast<int>(col_id)); } // Write predicate if (GetPredicate() == nullptr) { // Write the type output.WriteByte(static_cast<int8_t>(EXPRESSION_TYPE_INVALID)); } else { // Write the expression type ExpressionType expr_type = GetPredicate()->GetExpressionType(); output.WriteByte(static_cast<int8_t>(expr_type)); } // Write parent, but parent seems never be set or used right now if (GetParent() == nullptr) { // Write the type output.WriteByte(static_cast<int8_t>(PLAN_NODE_TYPE_INVALID)); } else { // Write the parent type PlanNodeType parent_type = GetParent()->GetPlanNodeType(); output.WriteByte(static_cast<int8_t>(parent_type)); // Write parent GetParent()->SerializeTo(output); } // Write the total length int32_t sz = static_cast<int32_t>(output.Position() - start - sizeof(int)); PL_ASSERT(sz > 0); output.WriteIntAt(start, sz); return true; }
hash_t InsertPlan::Hash() const { auto type = GetPlanNodeType(); hash_t hash = HashUtil::Hash(&type); hash = HashUtil::CombineHashes(hash, GetTable()->Hash()); if (GetChildren().size() == 0) { auto bulk_insert_count = GetBulkInsertCount(); hash = HashUtil::CombineHashes(hash, HashUtil::Hash(&bulk_insert_count)); } return HashUtil::CombineHashes(hash, AbstractPlan::Hash()); }
TEST_F(InsertSQLTests, InsertMultipleValues) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->CreateDatabase(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); CreateAndLoadTable(); std::vector<ResultValue> result; std::vector<FieldInfo> tuple_descriptor; std::string error_message; int rows_changed; std::unique_ptr<optimizer::AbstractOptimizer> optimizer( new optimizer::Optimizer()); // INSERT multiple tuples std::string query("INSERT INTO test VALUES (6, 11, 888), (7, 77, 999);"); txn = txn_manager.BeginTransaction(); auto plan = TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query, txn); EXPECT_EQ(plan->GetPlanNodeType(), PlanNodeType::INSERT); txn_manager.CommitTransaction(txn); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, query, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(2, rows_changed); // SELECT to find out if the tuples are correctly inserted TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test WHERE a=6", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); EXPECT_EQ("6", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("11", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("888", TestingSQLUtil::GetResultValueAsString(result, 2)); // SELECT to find out if the tuples are correctly inserted TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test WHERE a=7", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); EXPECT_EQ("7", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("77", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("999", TestingSQLUtil::GetResultValueAsString(result, 2)); // free the database just created txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->DropDatabaseWithName(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); }
bool InsertPlan::operator==(const AbstractPlan &rhs) const { if (GetPlanNodeType() != rhs.GetPlanNodeType()) return false; auto &other = static_cast<const planner::InsertPlan &>(rhs); auto *table = GetTable(); auto *other_table = other.GetTable(); PELOTON_ASSERT(table && other_table); if (*table != *other_table) return false; if (GetChildren().size() == 0) { if (other.GetChildren().size() != 0) return false; if (GetBulkInsertCount() != other.GetBulkInsertCount()) return false; } return AbstractPlan::operator==(rhs); }
TEST_F(InsertSQLTests, InsertTooLargeVarchar) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->CreateDatabase(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); CreateAndLoadTable3(); std::vector<ResultValue> result; std::vector<FieldInfo> tuple_descriptor; std::string error_message; int rows_changed; std::unique_ptr<optimizer::AbstractOptimizer> optimizer( new optimizer::Optimizer()); std::string query("INSERT INTO test3 VALUES(1, 'abcd', 'abcdefghij');"); // std::string query("INSERT INTO test3 VALUES(1, 'abcd', 'abcdefghijk');"); txn = txn_manager.BeginTransaction(); // This should be re-enabled when the check is properly done in catalog // It used to be done at the insert query level // EXPECT_THROW(TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query, // txn, peloton::Exception); auto plan = TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query, txn); EXPECT_EQ(plan->GetPlanNodeType(), PlanNodeType::INSERT); txn_manager.CommitTransaction(txn); rows_changed = 0; TestingSQLUtil::ExecuteSQLQuery(query, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(1, rows_changed); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test3;", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); // free the database just created txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->DropDatabaseWithName(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); }
/** * Therefore a SeqScanPlan is serialized as: * [(int) total size] * [(int8_t) plan type] * [(int) database_id] * [(int) table_id] * [(int) num column_id] * [(int) column id...] * [(int8_t) expr type] : if invalid, predicate is null * [(bytes) predicate] : predicate is Expression * [(int8_t) plan type] : if invalid, parent is null * [(bytes) parent] : parent is also a plan */ bool SeqScanPlan::DeserializeFrom(SerializeInput &input) { // Read the size of SeqScanPlan class input.ReadInt(); // Read the type UNUSED_ATTRIBUTE PlanNodeType plan_type = (PlanNodeType)input.ReadEnumInSingleByte(); PL_ASSERT(plan_type == GetPlanNodeType()); // Read database id oid_t database_oid = input.ReadInt(); // Read table id oid_t table_oid = input.ReadInt(); // Get table and set it to the member storage::DataTable *target_table = static_cast<storage::DataTable *>( catalog::Catalog::GetInstance()->GetTableWithOid(database_oid, table_oid)); SetTargetTable(target_table); // Read the number of column_id and set them to column_ids_ oid_t columnid_count = input.ReadInt(); for (oid_t it = 0; it < columnid_count; it++) { oid_t column_id = input.ReadInt(); SetColumnId(column_id); } // Read the type ExpressionType expr_type = (ExpressionType)input.ReadEnumInSingleByte(); // Predicate deserialization if (expr_type != EXPRESSION_TYPE_INVALID) { switch (expr_type) { // case EXPRESSION_TYPE_COMPARE_IN: // predicate_ = // std::unique_ptr<EXPRESSION_TYPE_COMPARE_IN>(new // ComparisonExpression (101)); // predicate_.DeserializeFrom(input); // break; default: { LOG_ERROR( "Expression deserialization :: Unsupported EXPRESSION_TYPE: %u ", expr_type); break; } } } // Read the type of parent PlanNodeType parent_type = (PlanNodeType)input.ReadEnumInSingleByte(); // Parent deserialization if (parent_type != PLAN_NODE_TYPE_INVALID) { switch (expr_type) { // case EXPRESSION_TYPE_COMPARE_IN: // predicate_ = // std::unique_ptr<EXPRESSION_TYPE_COMPARE_IN>(new // ComparisonExpression (101)); // predicate_.DeserializeFrom(input); // break; default: { LOG_ERROR("Parent deserialization :: Unsupported PlanNodeType: %u ", expr_type); break; } } } return true; }
TEST_F(InsertSQLTests, InsertIntoSelectColumn) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->CreateDatabase(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); CreateAndLoadTable6(); CreateAndLoadTable7(); std::vector<ResultValue> result; std::vector<FieldInfo> tuple_descriptor; std::string error_message; int rows_changed; std::unique_ptr<optimizer::AbstractOptimizer> optimizer( new optimizer::Optimizer()); // TEST CASE 1 std::string query_1("INSERT INTO test6 SELECT b,a,c FROM test7;"); txn = txn_manager.BeginTransaction(); auto plan = TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query_1, txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(plan->GetPlanNodeType(), PlanNodeType::INSERT); TestingSQLUtil::ExecuteSQLQueryWithOptimizer(optimizer, query_1, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(4, rows_changed); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test6 WHERE a=8", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); EXPECT_EQ("8", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("55", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("999", TestingSQLUtil::GetResultValueAsString(result, 2)); // TEST CASE 2 std::string query_2("INSERT INTO test7 SELECT * FROM test6 WHERE a=1;"); TestingSQLUtil::ExecuteSQLQueryWithOptimizer(optimizer, query_2, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(1, rows_changed); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test7 WHERE a=1", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); EXPECT_EQ("1", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("22", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("333", TestingSQLUtil::GetResultValueAsString(result, 2)); // TEST CASE 3 std::string query_3("INSERT INTO test7 SELECT b,a,c FROM test6 WHERE a=2;"); TestingSQLUtil::ExecuteSQLQueryWithOptimizer(optimizer, query_3, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(1, rows_changed); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test7 WHERE a=11", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(3, result.size()); EXPECT_EQ("11", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("2", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("0", TestingSQLUtil::GetResultValueAsString(result, 2)); // free the database just created txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->DropDatabaseWithName(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); }
TEST_F(InsertSQLTests, InsertIntoSelectSimpleAllType) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->CreateDatabase(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); CreateAndLoadTable4(); CreateAndLoadTable5(); std::vector<ResultValue> result; std::vector<FieldInfo> tuple_descriptor; std::string error_message; int rows_changed; std::unique_ptr<optimizer::AbstractOptimizer> optimizer( new optimizer::Optimizer()); // TEST CASE 1 std::string query_1("INSERT INTO test5 SELECT * FROM test4;"); txn = txn_manager.BeginTransaction(); auto plan = TestingSQLUtil::GeneratePlanWithOptimizer(optimizer, query_1, txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(plan->GetPlanNodeType(), PlanNodeType::INSERT); TestingSQLUtil::ExecuteSQLQueryWithOptimizer(optimizer, query_1, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(2, rows_changed); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test4 WHERE a=1", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(11, result.size()); EXPECT_EQ("1", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("2", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("3", TestingSQLUtil::GetResultValueAsString(result, 2)); EXPECT_EQ("4", TestingSQLUtil::GetResultValueAsString(result, 3)); EXPECT_EQ("5.1", TestingSQLUtil::GetResultValueAsString(result, 4)); EXPECT_EQ("6.1", TestingSQLUtil::GetResultValueAsString(result, 5)); EXPECT_EQ("2017-10-10 00:00:00.000000+00", TestingSQLUtil::GetResultValueAsString(result, 6)); EXPECT_EQ("A", TestingSQLUtil::GetResultValueAsString(result, 7)); EXPECT_EQ("a", TestingSQLUtil::GetResultValueAsString(result, 8)); EXPECT_EQ('1', TestingSQLUtil::GetResultValueAsString(result, 9).at(0)); EXPECT_EQ("true", TestingSQLUtil::GetResultValueAsString(result, 10)); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test5 WHERE a=1", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(11, result.size()); EXPECT_EQ("1", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("2", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("3", TestingSQLUtil::GetResultValueAsString(result, 2)); EXPECT_EQ("4", TestingSQLUtil::GetResultValueAsString(result, 3)); EXPECT_EQ("5.1", TestingSQLUtil::GetResultValueAsString(result, 4)); EXPECT_EQ("6.1", TestingSQLUtil::GetResultValueAsString(result, 5)); EXPECT_EQ("2017-10-10 00:00:00.000000+00", TestingSQLUtil::GetResultValueAsString(result, 6)); EXPECT_EQ("A", TestingSQLUtil::GetResultValueAsString(result, 7)); EXPECT_EQ("a", TestingSQLUtil::GetResultValueAsString(result, 8)); EXPECT_EQ('1', TestingSQLUtil::GetResultValueAsString(result, 9).at(0)); EXPECT_EQ("true", TestingSQLUtil::GetResultValueAsString(result, 10)); TestingSQLUtil::ExecuteSQLQueryWithOptimizer( optimizer, "SELECT * FROM test5 WHERE a=11", result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(11, result.size()); EXPECT_EQ("11", TestingSQLUtil::GetResultValueAsString(result, 0)); EXPECT_EQ("12", TestingSQLUtil::GetResultValueAsString(result, 1)); EXPECT_EQ("13", TestingSQLUtil::GetResultValueAsString(result, 2)); EXPECT_EQ("14", TestingSQLUtil::GetResultValueAsString(result, 3)); EXPECT_EQ("15.1", TestingSQLUtil::GetResultValueAsString(result, 4)); EXPECT_EQ("16.1", TestingSQLUtil::GetResultValueAsString(result, 5)); EXPECT_EQ("2017-10-11 00:00:00.000000+00", TestingSQLUtil::GetResultValueAsString(result, 6)); EXPECT_EQ("B", TestingSQLUtil::GetResultValueAsString(result, 7)); EXPECT_EQ("b", TestingSQLUtil::GetResultValueAsString(result, 8)); EXPECT_EQ('2', TestingSQLUtil::GetResultValueAsString(result, 9).at(0)); EXPECT_EQ("false", TestingSQLUtil::GetResultValueAsString(result, 10)); // free the database just created txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->DropDatabaseWithName(txn, DEFAULT_DB_NAME); txn_manager.CommitTransaction(txn); }