1 // Copyright (C) 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "icing/index/iterator/section-restrict-data.h"
16
17 #include <set>
18 #include <string>
19 #include <unordered_map>
20 #include <utility>
21
22 #include "icing/text_classifier/lib3/utils/base/statusor.h"
23 #include "icing/schema/schema-store.h"
24 #include "icing/schema/section.h"
25 #include "icing/store/document-filter-data.h"
26 #include "icing/store/document-id.h"
27
28 namespace icing {
29 namespace lib {
30
GenerateSectionMask(const std::string & schema_type,const std::set<std::string> & target_sections) const31 SectionIdMask SectionRestrictData::GenerateSectionMask(
32 const std::string& schema_type,
33 const std::set<std::string>& target_sections) const {
34 SectionIdMask section_mask = kSectionIdMaskNone;
35 auto section_metadata_list = schema_store_.GetSectionMetadata(schema_type);
36 if (!section_metadata_list.ok()) {
37 // The current schema doesn't have section metadata.
38 return kSectionIdMaskNone;
39 }
40 for (const SectionMetadata& section_metadata :
41 *section_metadata_list.ValueOrDie()) {
42 if (target_sections.find(section_metadata.path) != target_sections.end()) {
43 section_mask |= UINT64_C(1) << section_metadata.id;
44 }
45 }
46 return section_mask;
47 }
48
ComputeAllowedSectionsMask(const std::string & schema_type)49 SectionIdMask SectionRestrictData::ComputeAllowedSectionsMask(
50 const std::string& schema_type) {
51 if (const auto type_property_mask_itr =
52 type_property_masks_.find(schema_type);
53 type_property_mask_itr != type_property_masks_.end()) {
54 return type_property_mask_itr->second;
55 }
56
57 // Section id mask of schema_type is never calculated before, so
58 // calculate it here and put it into type_property_masks_.
59 // - If type property filters of schema_type or wildcard (*) are
60 // specified, then create a mask according to the filters.
61 // - Otherwise, create a mask to match all properties.
62 SectionIdMask new_section_id_mask = kSectionIdMaskAll;
63 if (const auto itr = type_property_filters_.find(schema_type);
64 itr != type_property_filters_.end()) {
65 // Property filters defined for given schema type
66 new_section_id_mask = GenerateSectionMask(schema_type, itr->second);
67 } else if (const auto wildcard_itr = type_property_filters_.find(
68 std::string(SchemaStore::kSchemaTypeWildcard));
69 wildcard_itr != type_property_filters_.end()) {
70 // Property filters defined for wildcard entry
71 new_section_id_mask =
72 GenerateSectionMask(schema_type, wildcard_itr->second);
73 } else {
74 // Do not cache the section mask if no property filters apply to this schema
75 // type to avoid taking up unnecessary space.
76 return kSectionIdMaskAll;
77 }
78
79 type_property_masks_[schema_type] = new_section_id_mask;
80 return new_section_id_mask;
81 }
82
ComputeAllowedSectionsMask(DocumentId document_id)83 SectionIdMask SectionRestrictData::ComputeAllowedSectionsMask(
84 DocumentId document_id) {
85 auto data_optional =
86 document_store_.GetAliveDocumentFilterData(document_id, current_time_ms_);
87 if (!data_optional) {
88 // Ran into some error retrieving information on this document, skip
89 return kSectionIdMaskNone;
90 }
91 // Guaranteed that the DocumentFilterData exists at this point
92 SchemaTypeId schema_type_id = data_optional.value().schema_type_id();
93 auto schema_type_or = schema_store_.GetSchemaType(schema_type_id);
94 if (!schema_type_or.ok()) {
95 // Ran into error retrieving schema type, skip
96 return kSectionIdMaskNone;
97 }
98 const std::string* schema_type = std::move(schema_type_or).ValueOrDie();
99 return ComputeAllowedSectionsMask(*schema_type);
100 }
101
102 } // namespace lib
103 } // namespace icing
104