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; } }
bool QueryContext::ProtoIsValid(const serialization::QueryContext &proto, const CatalogDatabaseLite &database) { for (int i = 0; i < proto.aggregation_states_size(); ++i) { if (!AggregationOperationState::ProtoIsValid(proto.aggregation_states(i).aggregation_state(), database)) { return false; } } // Each GeneratorFunctionHandle object is serialized as a function name with // a list of arguments. Here checks that the arguments are valid TypedValue's. for (int i = 0; i < proto.generator_functions_size(); ++i) { const serialization::GeneratorFunctionHandle &func_proto = proto.generator_functions(i); for (int j = 0; j < func_proto.args_size(); ++j) { if (!TypedValue::ProtoIsValid(func_proto.args(j))) { return false; } } } for (int i = 0; i < proto.join_hash_tables_size(); ++i) { if (!JoinHashTableFactory::ProtoIsValid(proto.join_hash_tables(i).join_hash_table())) { return false; } } for (int i = 0; i < proto.insert_destinations_size(); ++i) { const serialization::InsertDestination &insert_destination_proto = proto.insert_destinations(i); const relation_id rel_id = insert_destination_proto.relation_id(); if (!database.hasRelationWithId(rel_id) || !InsertDestination::ProtoIsValid(insert_destination_proto, database.getRelationSchemaById(rel_id))) { return false; } } for (int i = 0; i < proto.lip_filters_size(); ++i) { if (!LIPFilterFactory::ProtoIsValid(proto.lip_filters(i))) { return false; } } for (int i = 0; i < proto.lip_filter_deployments_size(); ++i) { if (!LIPFilterDeployment::ProtoIsValid(proto.lip_filter_deployments(i))) { return false; } } for (int i = 0; i < proto.predicates_size(); ++i) { if (!PredicateFactory::ProtoIsValid(proto.predicates(i), database)) { return false; } } for (int i = 0; i < proto.scalar_groups_size(); ++i) { const serialization::QueryContext::ScalarGroup &scalar_group_proto = proto.scalar_groups(i); for (int j = 0; j < scalar_group_proto.scalars_size(); ++j) { if (!ScalarFactory::ProtoIsValid(scalar_group_proto.scalars(j), database)) { return false; } } } for (int i = 0; i < proto.sort_configs_size(); ++i) { if (!SortConfiguration::ProtoIsValid(proto.sort_configs(i), database)) { return false; } } for (int i = 0; i < proto.tuples_size(); ++i) { if (!Tuple::ProtoIsValid(proto.tuples(i))) { return false; } } for (int i = 0; i < proto.update_groups_size(); ++i) { const serialization::QueryContext::UpdateGroup &update_group_proto = proto.update_groups(i); const relation_id rel_id = update_group_proto.relation_id(); if (!database.hasRelationWithId(rel_id)) { return false; } const CatalogRelationSchema &rel = database.getRelationSchemaById(rel_id); for (int j = 0; j < update_group_proto.update_assignments_size(); ++j) { const serialization::QueryContext::UpdateGroup::UpdateAssignment &update_assignment_proto = update_group_proto.update_assignments(j); if (!rel.hasAttributeWithId(update_assignment_proto.attribute_id()) || !ScalarFactory::ProtoIsValid(update_assignment_proto.scalar(), database)) { return false; } } } for (int i = 0; i < proto.window_aggregation_states_size(); ++i) { if (!WindowAggregationOperationState::ProtoIsValid(proto.window_aggregation_states(i), database)) { return false; } } return proto.IsInitialized(); }
QueryContext::QueryContext(const serialization::QueryContext &proto, const CatalogDatabaseLite &database, StorageManager *storage_manager, const tmb::client_id scheduler_client_id, tmb::MessageBus *bus) { DCHECK(ProtoIsValid(proto, database)) << "Attempted to create QueryContext from an invalid proto description:\n" << proto.DebugString(); for (int i = 0; i < proto.aggregation_states_size(); ++i) { PartitionedAggregationOperationStates partitioned_aggregation_states; const serialization::QueryContext::AggregationOperationStateContext &aggr_state_context_proto = proto.aggregation_states(i); for (std::uint64_t j = 0; j < aggr_state_context_proto.num_partitions(); ++j) { partitioned_aggregation_states.emplace_back( AggregationOperationState::ReconstructFromProto(aggr_state_context_proto.aggregation_state(), database, storage_manager)); } aggregation_states_.push_back(move(partitioned_aggregation_states)); } for (int i = 0; i < proto.generator_functions_size(); ++i) { const GeneratorFunctionHandle *func_handle = GeneratorFunctionFactory::Instance().reconstructFromProto(proto.generator_functions(i)); DCHECK(func_handle != nullptr); generator_functions_.emplace_back( std::unique_ptr<const GeneratorFunctionHandle>(func_handle)); } for (int i = 0; i < proto.join_hash_tables_size(); ++i) { PartitionedJoinHashTables partitioned_join_hash_tables; const serialization::QueryContext::HashTableContext &hash_table_context_proto = proto.join_hash_tables(i); for (std::uint64_t j = 0; j < hash_table_context_proto.num_partitions(); ++j) { partitioned_join_hash_tables.emplace_back( JoinHashTableFactory::CreateResizableFromProto(hash_table_context_proto.join_hash_table(), storage_manager)); } join_hash_tables_.push_back(move(partitioned_join_hash_tables)); } for (int i = 0; i < proto.insert_destinations_size(); ++i) { const serialization::InsertDestination &insert_destination_proto = proto.insert_destinations(i); insert_destinations_.emplace_back(InsertDestination::ReconstructFromProto( proto.query_id(), insert_destination_proto, database.getRelationSchemaById(insert_destination_proto.relation_id()), storage_manager, scheduler_client_id, bus)); } for (int i = 0; i < proto.lip_filters_size(); ++i) { lip_filters_.emplace_back( std::unique_ptr<LIPFilter>( LIPFilterFactory::ReconstructFromProto(proto.lip_filters(i)))); } for (int i = 0; i < proto.lip_filter_deployments_size(); ++i) { lip_deployments_.emplace_back( std::make_unique<LIPFilterDeployment>( proto.lip_filter_deployments(i), lip_filters_)); } for (int i = 0; i < proto.predicates_size(); ++i) { predicates_.emplace_back( PredicateFactory::ReconstructFromProto(proto.predicates(i), database)); } for (int i = 0; i < proto.scalar_groups_size(); ++i) { vector<unique_ptr<const Scalar>> scalar_group; const serialization::QueryContext::ScalarGroup &scalar_group_proto = proto.scalar_groups(i); for (int j = 0; j < scalar_group_proto.scalars_size(); ++j) { scalar_group.emplace_back( ScalarFactory::ReconstructFromProto(scalar_group_proto.scalars(j), database)); } scalar_groups_.push_back(move(scalar_group)); } for (int i = 0; i < proto.sort_configs_size(); ++i) { sort_configs_.emplace_back( SortConfiguration::ReconstructFromProto(proto.sort_configs(i), database)); } for (int i = 0; i < proto.tuples_size(); ++i) { tuples_.emplace_back(Tuple::ReconstructFromProto(proto.tuples(i))); } for (int i = 0; i < proto.update_groups_size(); ++i) { const serialization::QueryContext::UpdateGroup &update_group_proto = proto.update_groups(i); std::unordered_map<attribute_id, std::unique_ptr<const Scalar>> update_group; for (int j = 0; j < update_group_proto.update_assignments_size(); ++j) { const serialization::QueryContext::UpdateGroup::UpdateAssignment &update_assignment_proto = update_group_proto.update_assignments(j); unique_ptr<const Scalar> scalar( ScalarFactory::ReconstructFromProto(update_assignment_proto.scalar(), database)); update_group.emplace(update_assignment_proto.attribute_id(), move(scalar)); } update_groups_.push_back(move(update_group)); } for (int i = 0; i < proto.window_aggregation_states_size(); ++i) { window_aggregation_states_.emplace_back( WindowAggregationOperationState::ReconstructFromProto(proto.window_aggregation_states(i), database, storage_manager)); } }
bool ScalarFactory::ProtoIsValid(const serialization::Scalar &proto, const CatalogDatabaseLite &database) { // Check that proto is fully initialized. if (!proto.IsInitialized()) { return false; } // Check that the data_source is valid, and extensions if any. switch (proto.data_source()) { case serialization::Scalar::LITERAL: { return proto.HasExtension(serialization::ScalarLiteral::literal) && proto.HasExtension(serialization::ScalarLiteral::literal_type) && TypedValue::ProtoIsValid(proto.GetExtension(serialization::ScalarLiteral::literal)) && TypeFactory::ProtoIsValid(proto.GetExtension(serialization::ScalarLiteral::literal_type)); } case serialization::Scalar::ATTRIBUTE: { if (proto.HasExtension(serialization::ScalarAttribute::relation_id) && proto.HasExtension(serialization::ScalarAttribute::attribute_id)) { const relation_id rel_id = proto.GetExtension(serialization::ScalarAttribute::relation_id); const attribute_id attr_id = proto.GetExtension(serialization::ScalarAttribute::attribute_id); return database.hasRelationWithId(rel_id) && database.getRelationSchemaById(rel_id).hasAttributeWithId(attr_id); } break; } case serialization::Scalar::UNARY_EXPRESSION: { if (proto.HasExtension(serialization::ScalarUnaryExpression::operation) && proto.HasExtension(serialization::ScalarUnaryExpression::operand)) { return UnaryOperationFactory::ProtoIsValid(proto.GetExtension(serialization::ScalarUnaryExpression::operation)) && ProtoIsValid(proto.GetExtension(serialization::ScalarUnaryExpression::operand), database); } break; } case serialization::Scalar::BINARY_EXPRESSION: { if (proto.HasExtension(serialization::ScalarBinaryExpression::operation) && proto.HasExtension(serialization::ScalarBinaryExpression::left_operand) && proto.HasExtension(serialization::ScalarBinaryExpression::right_operand)) { return BinaryOperationFactory::ProtoIsValid( proto.GetExtension(serialization::ScalarBinaryExpression::operation)) && ProtoIsValid(proto.GetExtension(serialization::ScalarBinaryExpression::left_operand), database) && ProtoIsValid(proto.GetExtension(serialization::ScalarBinaryExpression::right_operand), database); } break; } case serialization::Scalar::CASE_EXPRESSION: { // Check result type. if (!(proto.HasExtension(serialization::ScalarCaseExpression::result_type) && TypeFactory::ProtoIsValid(proto.GetExtension( serialization::ScalarCaseExpression::result_type)))) { return false; } // Check when-predicates and result expressions. if (proto.ExtensionSize(serialization::ScalarCaseExpression::when_predicate) == proto.ExtensionSize(serialization::ScalarCaseExpression::result_expression)) { for (int case_num = 0; case_num < proto.ExtensionSize(serialization::ScalarCaseExpression::when_predicate); ++case_num) { if (!PredicateFactory::ProtoIsValid( proto.GetExtension( serialization::ScalarCaseExpression::when_predicate, case_num), database)) { return false; } if (!ProtoIsValid( proto.GetExtension(serialization::ScalarCaseExpression::result_expression, case_num), database)) { return false; } } } else { return false; } // Check else-result expression. if (!(proto.HasExtension(serialization::ScalarCaseExpression::else_result_expression) && ProtoIsValid(proto.GetExtension(serialization::ScalarCaseExpression::else_result_expression), database))) { return false; } // Everything checks out. return true; } default: { break; } } return false; }