bool WorkOrderFactory::ProtoIsValid(const serialization::WorkOrder &proto, const CatalogDatabaseLite &catalog_database, const QueryContext &query_context) { switch (proto.work_order_type()) { case serialization::AGGREGATION: { return proto.HasExtension(serialization::AggregationWorkOrder::block_id) && proto.HasExtension(serialization::AggregationWorkOrder::aggr_state_index) && query_context.isValidAggregationStateId( proto.GetExtension(serialization::AggregationWorkOrder::aggr_state_index)); } case serialization::BUILD_HASH: { if (!proto.HasExtension(serialization::BuildHashWorkOrder::relation_id)) { return false; } const relation_id rel_id = proto.GetExtension(serialization::BuildHashWorkOrder::relation_id); if (!catalog_database.hasRelationWithId(rel_id)) { return false; } const CatalogRelationSchema &relation = catalog_database.getRelationSchemaById(rel_id); for (int i = 0; i < proto.ExtensionSize(serialization::BuildHashWorkOrder::join_key_attributes); ++i) { if (!relation.hasAttributeWithId( proto.GetExtension(serialization::BuildHashWorkOrder::join_key_attributes, i))) { return false; } } return proto.HasExtension(serialization::BuildHashWorkOrder::any_join_key_attributes_nullable) && proto.HasExtension(serialization::BuildHashWorkOrder::block_id) && proto.HasExtension(serialization::BuildHashWorkOrder::join_hash_table_index) && query_context.isValidJoinHashTableId( proto.GetExtension(serialization::BuildHashWorkOrder::join_hash_table_index)); } case serialization::DELETE: { return proto.HasExtension(serialization::DeleteWorkOrder::relation_id) && catalog_database.hasRelationWithId( proto.GetExtension(serialization::DeleteWorkOrder::relation_id)) && proto.HasExtension(serialization::DeleteWorkOrder::predicate_index) && query_context.isValidPredicate( proto.GetExtension(serialization::DeleteWorkOrder::predicate_index)) && proto.HasExtension(serialization::DeleteWorkOrder::block_id) && proto.HasExtension(serialization::DeleteWorkOrder::operator_index); } case serialization::DESTROY_HASH: { return proto.HasExtension(serialization::DestroyHashWorkOrder::join_hash_table_index) && query_context.isValidJoinHashTableId( proto.GetExtension(serialization::DestroyHashWorkOrder::join_hash_table_index)); } case serialization::DROP_TABLE: { return true; } case serialization::FINALIZE_AGGREGATION: { return proto.HasExtension(serialization::FinalizeAggregationWorkOrder::aggr_state_index) && query_context.isValidAggregationStateId( proto.GetExtension(serialization::FinalizeAggregationWorkOrder::aggr_state_index)) && proto.HasExtension(serialization::FinalizeAggregationWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::FinalizeAggregationWorkOrder::insert_destination_index)); } case serialization::HASH_JOIN: { if (!proto.HasExtension(serialization::HashJoinWorkOrder::hash_join_work_order_type)) { return false; } const auto hash_join_work_order_type = proto.GetExtension(serialization::HashJoinWorkOrder::hash_join_work_order_type); if (!serialization::HashJoinWorkOrder_HashJoinWorkOrderType_IsValid(hash_join_work_order_type)) { return false; } if (!proto.HasExtension(serialization::HashJoinWorkOrder::build_relation_id) || !proto.HasExtension(serialization::HashJoinWorkOrder::probe_relation_id)) { return false; } const relation_id build_relation_id = proto.GetExtension(serialization::HashJoinWorkOrder::build_relation_id); if (!catalog_database.hasRelationWithId(build_relation_id)) { return false; } const relation_id probe_relation_id = proto.GetExtension(serialization::HashJoinWorkOrder::probe_relation_id); if (!catalog_database.hasRelationWithId(probe_relation_id)) { return false; } const CatalogRelationSchema &build_relation = catalog_database.getRelationSchemaById(build_relation_id); const CatalogRelationSchema &probe_relation = catalog_database.getRelationSchemaById(probe_relation_id); for (int i = 0; i < proto.ExtensionSize(serialization::HashJoinWorkOrder::join_key_attributes); ++i) { const attribute_id attr_id = proto.GetExtension(serialization::HashJoinWorkOrder::join_key_attributes, i); if (!build_relation.hasAttributeWithId(attr_id) || !probe_relation.hasAttributeWithId(attr_id)) { return false; } } if (hash_join_work_order_type == serialization::HashJoinWorkOrder::HASH_OUTER_JOIN) { if (!proto.HasExtension(serialization::HashJoinWorkOrder::is_selection_on_build)) { return false; } } else { if (!proto.HasExtension(serialization::HashJoinWorkOrder::residual_predicate_index) || !query_context.isValidPredicate( proto.GetExtension(serialization::HashJoinWorkOrder::residual_predicate_index))) { return false; } } return proto.HasExtension(serialization::HashJoinWorkOrder::any_join_key_attributes_nullable) && proto.HasExtension(serialization::HashJoinWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::HashJoinWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::HashJoinWorkOrder::join_hash_table_index) && query_context.isValidJoinHashTableId( proto.GetExtension(serialization::HashJoinWorkOrder::join_hash_table_index)) && proto.HasExtension(serialization::HashJoinWorkOrder::selection_index) && query_context.isValidScalarGroupId( proto.GetExtension(serialization::HashJoinWorkOrder::selection_index)) && proto.HasExtension(serialization::HashJoinWorkOrder::block_id); } case serialization::INSERT: { return proto.HasExtension(serialization::InsertWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::InsertWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::InsertWorkOrder::tuple_index) && query_context.isValidTupleId( proto.GetExtension(serialization::InsertWorkOrder::tuple_index)); } case serialization::NESTED_LOOP_JOIN: { if (!proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::left_relation_id) || !proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::right_relation_id)) { return false; } const relation_id left_relation_id = proto.GetExtension(serialization::NestedLoopsJoinWorkOrder::left_relation_id); if (!catalog_database.hasRelationWithId(left_relation_id)) { return false; } const relation_id right_relation_id = proto.GetExtension(serialization::NestedLoopsJoinWorkOrder::right_relation_id); if (!catalog_database.hasRelationWithId(right_relation_id)) { return false; } return proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::left_block_id) && proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::right_block_id) && proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::NestedLoopsJoinWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::join_predicate_index) && query_context.isValidPredicate( proto.GetExtension(serialization::NestedLoopsJoinWorkOrder::join_predicate_index)) && proto.HasExtension(serialization::NestedLoopsJoinWorkOrder::selection_index) && query_context.isValidScalarGroupId( proto.GetExtension(serialization::NestedLoopsJoinWorkOrder::selection_index)); } case serialization::SAMPLE: { return catalog_database.hasRelationWithId(proto.GetExtension(serialization::SampleWorkOrder::relation_id)) && proto.HasExtension(serialization::SampleWorkOrder::block_id) && proto.HasExtension(serialization::SampleWorkOrder::is_block_sample) && proto.HasExtension(serialization::SampleWorkOrder::percentage) && proto.HasExtension(serialization::SampleWorkOrder::insert_destination_index); } case serialization::SAVE_BLOCKS: { return proto.HasExtension(serialization::SaveBlocksWorkOrder::block_id) && proto.HasExtension(serialization::SaveBlocksWorkOrder::force); } case serialization::SELECT: { if (!proto.HasExtension(serialization::SelectWorkOrder::relation_id) || !proto.HasExtension(serialization::SelectWorkOrder::simple_projection) || !proto.HasExtension(serialization::SelectWorkOrder::selection_index)) { return false; } const relation_id rel_id = proto.GetExtension(serialization::SelectWorkOrder::relation_id); if (!catalog_database.hasRelationWithId(rel_id)) { return false; } const CatalogRelationSchema &relation = catalog_database.getRelationSchemaById(rel_id); for (int i = 0; i < proto.ExtensionSize(serialization::SelectWorkOrder::simple_selection); ++i) { if (!relation.hasAttributeWithId( proto.GetExtension(serialization::SelectWorkOrder::simple_selection, i))) { return false; } } if (proto.GetExtension(serialization::SelectWorkOrder::simple_projection) == query_context.isValidScalarGroupId( proto.GetExtension(serialization::SelectWorkOrder::selection_index))) { return false; } return proto.HasExtension(serialization::SelectWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::SelectWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::SelectWorkOrder::predicate_index) && query_context.isValidPredicate( proto.GetExtension(serialization::SelectWorkOrder::predicate_index)) && proto.HasExtension(serialization::SelectWorkOrder::block_id); } case serialization::SORT_MERGE_RUN: { // In Protobuf 2.6, proto.HasExtension does not work for the repeated // message field, but Protobuf 3.0 beta works. // TODO(zuyu): Validate serialization::SortMergeRunWorkOrder::runs. return proto.HasExtension(serialization::SortMergeRunWorkOrder::sort_config_index) && query_context.isValidSortConfigId( proto.GetExtension(serialization::SortMergeRunWorkOrder::sort_config_index)) && proto.HasExtension(serialization::SortMergeRunWorkOrder::top_k) && proto.HasExtension(serialization::SortMergeRunWorkOrder::merge_level) && proto.HasExtension(serialization::SortMergeRunWorkOrder::relation_id) && catalog_database.hasRelationWithId( proto.GetExtension(serialization::SortMergeRunWorkOrder::relation_id)) && proto.HasExtension(serialization::SortMergeRunWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::SortMergeRunWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::SortMergeRunWorkOrder::operator_index); } case serialization::SORT_RUN_GENERATION: { return proto.HasExtension(serialization::SortRunGenerationWorkOrder::relation_id) && catalog_database.hasRelationWithId( proto.GetExtension(serialization::SortRunGenerationWorkOrder::relation_id)) && proto.HasExtension(serialization::SortRunGenerationWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::SortRunGenerationWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::SortRunGenerationWorkOrder::sort_config_index) && query_context.isValidSortConfigId( proto.GetExtension(serialization::SortRunGenerationWorkOrder::sort_config_index)) && proto.HasExtension(serialization::SortRunGenerationWorkOrder::block_id); } case serialization::TABLE_GENERATOR: { return proto.HasExtension(serialization::TableGeneratorWorkOrder::generator_function_index) && query_context.isValidGeneratorFunctionId( proto.GetExtension(serialization::TableGeneratorWorkOrder::generator_function_index)) && proto.HasExtension(serialization::TableGeneratorWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::TableGeneratorWorkOrder::insert_destination_index)); } case serialization::TEXT_SCAN: { if (!proto.HasExtension(serialization::TextScanWorkOrder::field_terminator) || !proto.HasExtension(serialization::TextScanWorkOrder::process_escape_sequences) || !proto.HasExtension(serialization::TextScanWorkOrder::insert_destination_index) || !query_context.isValidInsertDestinationId( proto.GetExtension(serialization::TextScanWorkOrder::insert_destination_index))) { return false; } // Two fields are exclusive. if (proto.HasExtension(serialization::TextScanWorkOrder::filename) == proto.HasExtension(serialization::TextScanWorkOrder::text_blob)) { return false; } return proto.HasExtension(serialization::TextScanWorkOrder::filename) || proto.GetExtension(serialization::TextScanWorkOrder::text_blob).IsInitialized(); } case serialization::TEXT_SPLIT: { return proto.HasExtension(serialization::TextSplitWorkOrder::filename) && proto.HasExtension(serialization::TextSplitWorkOrder::process_escape_sequences) && proto.HasExtension(serialization::TextSplitWorkOrder::operator_index); } case serialization::UPDATE: { return proto.HasExtension(serialization::UpdateWorkOrder::relation_id) && catalog_database.hasRelationWithId( proto.GetExtension(serialization::UpdateWorkOrder::relation_id)) && proto.HasExtension(serialization::UpdateWorkOrder::insert_destination_index) && query_context.isValidInsertDestinationId( proto.GetExtension(serialization::UpdateWorkOrder::insert_destination_index)) && proto.HasExtension(serialization::UpdateWorkOrder::predicate_index) && query_context.isValidPredicate( proto.GetExtension(serialization::UpdateWorkOrder::predicate_index)) && proto.HasExtension(serialization::UpdateWorkOrder::update_group_index) && query_context.isValidUpdateGroupId( proto.GetExtension(serialization::UpdateWorkOrder::update_group_index)) && proto.HasExtension(serialization::UpdateWorkOrder::operator_index) && proto.HasExtension(serialization::UpdateWorkOrder::block_id); } default: return false; } }