xref: /aosp_15_r20/external/icing/icing/schema/schema-store.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1*8b6cd535SAndroid Build Coastguard Worker // Copyright (C) 2019 Google LLC
2*8b6cd535SAndroid Build Coastguard Worker //
3*8b6cd535SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*8b6cd535SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*8b6cd535SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*8b6cd535SAndroid Build Coastguard Worker //
7*8b6cd535SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*8b6cd535SAndroid Build Coastguard Worker //
9*8b6cd535SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*8b6cd535SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*8b6cd535SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*8b6cd535SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*8b6cd535SAndroid Build Coastguard Worker // limitations under the License.
14*8b6cd535SAndroid Build Coastguard Worker 
15*8b6cd535SAndroid Build Coastguard Worker #ifndef ICING_SCHEMA_SCHEMA_STORE_H_
16*8b6cd535SAndroid Build Coastguard Worker #define ICING_SCHEMA_SCHEMA_STORE_H_
17*8b6cd535SAndroid Build Coastguard Worker 
18*8b6cd535SAndroid Build Coastguard Worker #include <cstdint>
19*8b6cd535SAndroid Build Coastguard Worker #include <cstring>
20*8b6cd535SAndroid Build Coastguard Worker #include <limits>
21*8b6cd535SAndroid Build Coastguard Worker #include <memory>
22*8b6cd535SAndroid Build Coastguard Worker #include <optional>
23*8b6cd535SAndroid Build Coastguard Worker #include <string>
24*8b6cd535SAndroid Build Coastguard Worker #include <string_view>
25*8b6cd535SAndroid Build Coastguard Worker #include <unordered_map>
26*8b6cd535SAndroid Build Coastguard Worker #include <unordered_set>
27*8b6cd535SAndroid Build Coastguard Worker #include <utility>
28*8b6cd535SAndroid Build Coastguard Worker #include <vector>
29*8b6cd535SAndroid Build Coastguard Worker 
30*8b6cd535SAndroid Build Coastguard Worker #include "icing/text_classifier/lib3/utils/base/status.h"
31*8b6cd535SAndroid Build Coastguard Worker #include "icing/text_classifier/lib3/utils/base/statusor.h"
32*8b6cd535SAndroid Build Coastguard Worker #include "icing/absl_ports/canonical_errors.h"
33*8b6cd535SAndroid Build Coastguard Worker #include "icing/feature-flags.h"
34*8b6cd535SAndroid Build Coastguard Worker #include "icing/file/file-backed-proto.h"
35*8b6cd535SAndroid Build Coastguard Worker #include "icing/file/filesystem.h"
36*8b6cd535SAndroid Build Coastguard Worker #include "icing/file/version-util.h"
37*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/debug.pb.h"
38*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/document.pb.h"
39*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/logging.pb.h"
40*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/schema.pb.h"
41*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/search.pb.h"
42*8b6cd535SAndroid Build Coastguard Worker #include "icing/proto/storage.pb.h"
43*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/joinable-property.h"
44*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/schema-type-manager.h"
45*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/schema-util.h"
46*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/scorable_property_manager.h"
47*8b6cd535SAndroid Build Coastguard Worker #include "icing/schema/section.h"
48*8b6cd535SAndroid Build Coastguard Worker #include "icing/store/document-filter-data.h"
49*8b6cd535SAndroid Build Coastguard Worker #include "icing/store/key-mapper.h"
50*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/clock.h"
51*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/crc32.h"
52*8b6cd535SAndroid Build Coastguard Worker #include "icing/util/status-macros.h"
53*8b6cd535SAndroid Build Coastguard Worker 
54*8b6cd535SAndroid Build Coastguard Worker namespace icing {
55*8b6cd535SAndroid Build Coastguard Worker namespace lib {
56*8b6cd535SAndroid Build Coastguard Worker 
57*8b6cd535SAndroid Build Coastguard Worker // Holds the ground truth schema proto. Tracks compatible changes to the schema
58*8b6cd535SAndroid Build Coastguard Worker // and will update any derived data based on the schema proto, such as Sections,
59*8b6cd535SAndroid Build Coastguard Worker // SchemaTypeConfigs, PropertyConfigs, and SchemaTypeIds. To ensure they have
60*8b6cd535SAndroid Build Coastguard Worker // the most up-to-date data, callers should not save instances themselves and
61*8b6cd535SAndroid Build Coastguard Worker // should always call Get* from the SchemaStore.
62*8b6cd535SAndroid Build Coastguard Worker class SchemaStore {
63*8b6cd535SAndroid Build Coastguard Worker  public:
64*8b6cd535SAndroid Build Coastguard Worker   struct LegacyHeader {
65*8b6cd535SAndroid Build Coastguard Worker     // Holds the magic as a quick sanity check against file corruption.
66*8b6cd535SAndroid Build Coastguard Worker     int32_t magic;
67*8b6cd535SAndroid Build Coastguard Worker 
68*8b6cd535SAndroid Build Coastguard Worker     // Checksum of the SchemaStore's sub-component's checksums.
69*8b6cd535SAndroid Build Coastguard Worker     uint32_t checksum;
70*8b6cd535SAndroid Build Coastguard Worker   };
71*8b6cd535SAndroid Build Coastguard Worker 
72*8b6cd535SAndroid Build Coastguard Worker   class Header {
73*8b6cd535SAndroid Build Coastguard Worker    public:
74*8b6cd535SAndroid Build Coastguard Worker     static constexpr int32_t kMagic = 0x72650d0a;
75*8b6cd535SAndroid Build Coastguard Worker 
Header(const Filesystem * filesystem,std::string path)76*8b6cd535SAndroid Build Coastguard Worker     explicit Header(const Filesystem* filesystem, std::string path)
77*8b6cd535SAndroid Build Coastguard Worker         : path_(std::move(path)), filesystem_(filesystem) {}
78*8b6cd535SAndroid Build Coastguard Worker 
Header(Header && other)79*8b6cd535SAndroid Build Coastguard Worker     Header(Header&& other)
80*8b6cd535SAndroid Build Coastguard Worker         : serialized_header_(std::move(other.serialized_header_)),
81*8b6cd535SAndroid Build Coastguard Worker           path_(std::move(other.path_)),
82*8b6cd535SAndroid Build Coastguard Worker           header_fd_(std::move(other.header_fd_)),
83*8b6cd535SAndroid Build Coastguard Worker           filesystem_(other.filesystem_),
84*8b6cd535SAndroid Build Coastguard Worker           dirty_(other.dirty_) {}
85*8b6cd535SAndroid Build Coastguard Worker 
86*8b6cd535SAndroid Build Coastguard Worker     Header& operator=(Header&& other) {
87*8b6cd535SAndroid Build Coastguard Worker       serialized_header_ = std::move(other.serialized_header_);
88*8b6cd535SAndroid Build Coastguard Worker       path_ = std::move(other.path_);
89*8b6cd535SAndroid Build Coastguard Worker       header_fd_ = std::move(other.header_fd_);
90*8b6cd535SAndroid Build Coastguard Worker       filesystem_ = other.filesystem_;
91*8b6cd535SAndroid Build Coastguard Worker       dirty_ = other.dirty_;
92*8b6cd535SAndroid Build Coastguard Worker       return *this;
93*8b6cd535SAndroid Build Coastguard Worker     }
94*8b6cd535SAndroid Build Coastguard Worker 
95*8b6cd535SAndroid Build Coastguard Worker     struct SerializedHeader {
SerializedHeaderSerializedHeader96*8b6cd535SAndroid Build Coastguard Worker       explicit SerializedHeader()
97*8b6cd535SAndroid Build Coastguard Worker           : magic(kMagic),
98*8b6cd535SAndroid Build Coastguard Worker             checksum(0),
99*8b6cd535SAndroid Build Coastguard Worker             overlay_created(false),
100*8b6cd535SAndroid Build Coastguard Worker             min_overlay_version_compatibility(
101*8b6cd535SAndroid Build Coastguard Worker                 std::numeric_limits<int32_t>::max()) {
102*8b6cd535SAndroid Build Coastguard Worker         memset(overlay_created_padding, 0, kOverlayCreatedPaddingSize);
103*8b6cd535SAndroid Build Coastguard Worker         memset(padding, 0, kPaddingSize);
104*8b6cd535SAndroid Build Coastguard Worker       }
105*8b6cd535SAndroid Build Coastguard Worker       // Holds the magic as a quick sanity check against file corruption.
106*8b6cd535SAndroid Build Coastguard Worker       int32_t magic;
107*8b6cd535SAndroid Build Coastguard Worker 
108*8b6cd535SAndroid Build Coastguard Worker       // Checksum of the SchemaStore's sub-component's checksums.
109*8b6cd535SAndroid Build Coastguard Worker       uint32_t checksum;
110*8b6cd535SAndroid Build Coastguard Worker 
111*8b6cd535SAndroid Build Coastguard Worker       bool overlay_created;
112*8b6cd535SAndroid Build Coastguard Worker       // Three bytes of padding due to the fact that
113*8b6cd535SAndroid Build Coastguard Worker       // min_overlay_version_compatibility_ has an alignof() == 4 and the offset
114*8b6cd535SAndroid Build Coastguard Worker       // of overlay_created_padding_ == 9.
115*8b6cd535SAndroid Build Coastguard Worker       static constexpr int kOverlayCreatedPaddingSize = 3;
116*8b6cd535SAndroid Build Coastguard Worker       uint8_t overlay_created_padding[kOverlayCreatedPaddingSize];
117*8b6cd535SAndroid Build Coastguard Worker 
118*8b6cd535SAndroid Build Coastguard Worker       int32_t min_overlay_version_compatibility;
119*8b6cd535SAndroid Build Coastguard Worker 
120*8b6cd535SAndroid Build Coastguard Worker       static constexpr int kPaddingSize = 1008;
121*8b6cd535SAndroid Build Coastguard Worker       // Padding exists just to reserve space for additional values.
122*8b6cd535SAndroid Build Coastguard Worker       uint8_t padding[kPaddingSize];
123*8b6cd535SAndroid Build Coastguard Worker     };
124*8b6cd535SAndroid Build Coastguard Worker     static_assert(sizeof(SerializedHeader) == 1024);
125*8b6cd535SAndroid Build Coastguard Worker 
126*8b6cd535SAndroid Build Coastguard Worker     // RETURNS:
127*8b6cd535SAndroid Build Coastguard Worker     //   - On success, a valid Header instance
128*8b6cd535SAndroid Build Coastguard Worker     //   - NOT_FOUND if header file doesn't exist
129*8b6cd535SAndroid Build Coastguard Worker     //   - INTERNAL if unable to read header
130*8b6cd535SAndroid Build Coastguard Worker     static libtextclassifier3::StatusOr<Header> Read(
131*8b6cd535SAndroid Build Coastguard Worker         const Filesystem* filesystem, std::string path);
132*8b6cd535SAndroid Build Coastguard Worker 
133*8b6cd535SAndroid Build Coastguard Worker     libtextclassifier3::Status Write();
134*8b6cd535SAndroid Build Coastguard Worker 
135*8b6cd535SAndroid Build Coastguard Worker     libtextclassifier3::Status PersistToDisk();
136*8b6cd535SAndroid Build Coastguard Worker 
magic()137*8b6cd535SAndroid Build Coastguard Worker     int32_t magic() const { return serialized_header_.magic; }
138*8b6cd535SAndroid Build Coastguard Worker 
checksum()139*8b6cd535SAndroid Build Coastguard Worker     uint32_t checksum() const { return serialized_header_.checksum; }
set_checksum(uint32_t checksum)140*8b6cd535SAndroid Build Coastguard Worker     void set_checksum(uint32_t checksum) {
141*8b6cd535SAndroid Build Coastguard Worker       dirty_ = true;
142*8b6cd535SAndroid Build Coastguard Worker       serialized_header_.checksum = checksum;
143*8b6cd535SAndroid Build Coastguard Worker     }
144*8b6cd535SAndroid Build Coastguard Worker 
overlay_created()145*8b6cd535SAndroid Build Coastguard Worker     bool overlay_created() const { return serialized_header_.overlay_created; }
146*8b6cd535SAndroid Build Coastguard Worker 
min_overlay_version_compatibility()147*8b6cd535SAndroid Build Coastguard Worker     int32_t min_overlay_version_compatibility() const {
148*8b6cd535SAndroid Build Coastguard Worker       return serialized_header_.min_overlay_version_compatibility;
149*8b6cd535SAndroid Build Coastguard Worker     }
150*8b6cd535SAndroid Build Coastguard Worker 
SetOverlayInfo(bool overlay_created,int32_t min_overlay_version_compatibility)151*8b6cd535SAndroid Build Coastguard Worker     void SetOverlayInfo(bool overlay_created,
152*8b6cd535SAndroid Build Coastguard Worker                         int32_t min_overlay_version_compatibility) {
153*8b6cd535SAndroid Build Coastguard Worker       dirty_ = true;
154*8b6cd535SAndroid Build Coastguard Worker       serialized_header_.overlay_created = overlay_created;
155*8b6cd535SAndroid Build Coastguard Worker       serialized_header_.min_overlay_version_compatibility =
156*8b6cd535SAndroid Build Coastguard Worker           min_overlay_version_compatibility;
157*8b6cd535SAndroid Build Coastguard Worker     }
158*8b6cd535SAndroid Build Coastguard Worker 
159*8b6cd535SAndroid Build Coastguard Worker    private:
Header(SerializedHeader serialized_header,std::string path,ScopedFd header_fd,const Filesystem * filesystem)160*8b6cd535SAndroid Build Coastguard Worker     explicit Header(SerializedHeader serialized_header, std::string path,
161*8b6cd535SAndroid Build Coastguard Worker                     ScopedFd header_fd, const Filesystem* filesystem)
162*8b6cd535SAndroid Build Coastguard Worker         : serialized_header_(std::move(serialized_header)),
163*8b6cd535SAndroid Build Coastguard Worker           path_(std::move(path)),
164*8b6cd535SAndroid Build Coastguard Worker           header_fd_(std::move(header_fd)),
165*8b6cd535SAndroid Build Coastguard Worker           filesystem_(filesystem),
166*8b6cd535SAndroid Build Coastguard Worker           dirty_(false) {}
167*8b6cd535SAndroid Build Coastguard Worker 
168*8b6cd535SAndroid Build Coastguard Worker     SerializedHeader serialized_header_;
169*8b6cd535SAndroid Build Coastguard Worker     std::string path_;
170*8b6cd535SAndroid Build Coastguard Worker     ScopedFd header_fd_;
171*8b6cd535SAndroid Build Coastguard Worker     const Filesystem* filesystem_;  // Not owned.
172*8b6cd535SAndroid Build Coastguard Worker     bool dirty_;
173*8b6cd535SAndroid Build Coastguard Worker   };
174*8b6cd535SAndroid Build Coastguard Worker 
175*8b6cd535SAndroid Build Coastguard Worker   // Holds information on what may have been affected by the new schema. This is
176*8b6cd535SAndroid Build Coastguard Worker   // generally data that other classes may depend on from the SchemaStore,
177*8b6cd535SAndroid Build Coastguard Worker   // so that we can know if we should go update those classes as well.
178*8b6cd535SAndroid Build Coastguard Worker   struct SetSchemaResult {
179*8b6cd535SAndroid Build Coastguard Worker     // Whether we are able to write the schema as determined by SetSchema's
180*8b6cd535SAndroid Build Coastguard Worker     // arguments. This boolean reflects SetSchema's logic, and does not reflect
181*8b6cd535SAndroid Build Coastguard Worker     // any system level IO errors that may prevent the schema from being written
182*8b6cd535SAndroid Build Coastguard Worker     // to file.
183*8b6cd535SAndroid Build Coastguard Worker     bool success = false;
184*8b6cd535SAndroid Build Coastguard Worker 
185*8b6cd535SAndroid Build Coastguard Worker     // SchemaTypeIds of schema types can be reassigned new SchemaTypeIds if:
186*8b6cd535SAndroid Build Coastguard Worker     //   1. Schema types are added in the middle of the SchemaProto
187*8b6cd535SAndroid Build Coastguard Worker     //   2. Schema types are removed from the middle of the SchemaProto
188*8b6cd535SAndroid Build Coastguard Worker     //   3. Schema types are reordered in the SchemaProto
189*8b6cd535SAndroid Build Coastguard Worker     //
190*8b6cd535SAndroid Build Coastguard Worker     // SchemaTypeIds are not changed if schema types are added/removed to the
191*8b6cd535SAndroid Build Coastguard Worker     // end of the SchemaProto.
192*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<SchemaTypeId> old_schema_type_ids_changed;
193*8b6cd535SAndroid Build Coastguard Worker 
194*8b6cd535SAndroid Build Coastguard Worker     // Schema types that have been removed from the new schema. Represented by
195*8b6cd535SAndroid Build Coastguard Worker     // the `schema_type` field in the SchemaTypeConfigProto.
196*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> schema_types_deleted_by_name;
197*8b6cd535SAndroid Build Coastguard Worker 
198*8b6cd535SAndroid Build Coastguard Worker     // Schema types that have been removed from the new schema. Represented by
199*8b6cd535SAndroid Build Coastguard Worker     // the SchemaTypeId assigned to this SchemaTypeConfigProto in the *old*
200*8b6cd535SAndroid Build Coastguard Worker     // schema.
201*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<SchemaTypeId> schema_types_deleted_by_id;
202*8b6cd535SAndroid Build Coastguard Worker 
203*8b6cd535SAndroid Build Coastguard Worker     // Schema types whose SchemaTypeConfigProto has changed in an incompatible
204*8b6cd535SAndroid Build Coastguard Worker     // manner in the new schema. Compatibility determined in
205*8b6cd535SAndroid Build Coastguard Worker     // SchemaUtil::ComputeCompatibilityDelta. Represented by the `schema_type`
206*8b6cd535SAndroid Build Coastguard Worker     // field in the SchemaTypeConfigProto.
207*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> schema_types_incompatible_by_name;
208*8b6cd535SAndroid Build Coastguard Worker 
209*8b6cd535SAndroid Build Coastguard Worker     // Schema types whose SchemaTypeConfigProto has changed in an incompatible
210*8b6cd535SAndroid Build Coastguard Worker     // manner in the new schema. Compatibility determined in
211*8b6cd535SAndroid Build Coastguard Worker     // SchemaUtil::ComputeCompatibilityDelta. Represented by the SchemaTypeId
212*8b6cd535SAndroid Build Coastguard Worker     // assigned to this SchemaTypeConfigProto in the *old* schema.
213*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<SchemaTypeId> schema_types_incompatible_by_id;
214*8b6cd535SAndroid Build Coastguard Worker 
215*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were added in the new schema. Represented by the
216*8b6cd535SAndroid Build Coastguard Worker     // `schema_type` field in the SchemaTypeConfigProto.
217*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> schema_types_new_by_name;
218*8b6cd535SAndroid Build Coastguard Worker 
219*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were changed in a way that was backwards compatible and
220*8b6cd535SAndroid Build Coastguard Worker     // didn't invalidate the index. Represented by the `schema_type` field in
221*8b6cd535SAndroid Build Coastguard Worker     // the SchemaTypeConfigProto.
222*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string>
223*8b6cd535SAndroid Build Coastguard Worker         schema_types_changed_fully_compatible_by_name;
224*8b6cd535SAndroid Build Coastguard Worker 
225*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were changed in a way that was backwards compatible,
226*8b6cd535SAndroid Build Coastguard Worker     // but invalidated the index. Represented by the `schema_type` field in the
227*8b6cd535SAndroid Build Coastguard Worker     // SchemaTypeConfigProto.
228*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> schema_types_index_incompatible_by_name;
229*8b6cd535SAndroid Build Coastguard Worker 
230*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were changed in a way that was backwards compatible,
231*8b6cd535SAndroid Build Coastguard Worker     // but invalidated the joinable cache. Represented by the `schema_type`
232*8b6cd535SAndroid Build Coastguard Worker     // field in the SchemaTypeConfigProto.
233*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> schema_types_join_incompatible_by_name;
234*8b6cd535SAndroid Build Coastguard Worker 
235*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were changed in a way that was backwards compatible,
236*8b6cd535SAndroid Build Coastguard Worker     // but inconsistent with the old schema so that the scorable property cache
237*8b6cd535SAndroid Build Coastguard Worker     // needs to be re-generated.
238*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<SchemaTypeId>
239*8b6cd535SAndroid Build Coastguard Worker         schema_types_scorable_property_inconsistent_by_id;
240*8b6cd535SAndroid Build Coastguard Worker 
241*8b6cd535SAndroid Build Coastguard Worker     // Schema types that were changed in a way that was backwards compatible,
242*8b6cd535SAndroid Build Coastguard Worker     // but inconsistent with the old schema so that the scorable property cache
243*8b6cd535SAndroid Build Coastguard Worker     // needs to be re-generated.
244*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string>
245*8b6cd535SAndroid Build Coastguard Worker         schema_types_scorable_property_inconsistent_by_name;
246*8b6cd535SAndroid Build Coastguard Worker   };
247*8b6cd535SAndroid Build Coastguard Worker 
248*8b6cd535SAndroid Build Coastguard Worker   struct ExpandedTypePropertyMask {
249*8b6cd535SAndroid Build Coastguard Worker     std::string schema_type;
250*8b6cd535SAndroid Build Coastguard Worker     std::unordered_set<std::string> paths;
251*8b6cd535SAndroid Build Coastguard Worker   };
252*8b6cd535SAndroid Build Coastguard Worker 
253*8b6cd535SAndroid Build Coastguard Worker   static constexpr std::string_view kSchemaTypeWildcard = "*";
254*8b6cd535SAndroid Build Coastguard Worker 
255*8b6cd535SAndroid Build Coastguard Worker   // Factory function to create a SchemaStore which does not take ownership
256*8b6cd535SAndroid Build Coastguard Worker   // of any input components, and all pointers must refer to valid objects that
257*8b6cd535SAndroid Build Coastguard Worker   // outlive the created SchemaStore instance. The base_dir must already exist.
258*8b6cd535SAndroid Build Coastguard Worker   // There does not need to be an existing schema already.
259*8b6cd535SAndroid Build Coastguard Worker   //
260*8b6cd535SAndroid Build Coastguard Worker   // If initialize_stats is present, the fields related to SchemaStore will be
261*8b6cd535SAndroid Build Coastguard Worker   // populated.
262*8b6cd535SAndroid Build Coastguard Worker   //
263*8b6cd535SAndroid Build Coastguard Worker   // Returns:
264*8b6cd535SAndroid Build Coastguard Worker   //   A SchemaStore on success
265*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION on any null pointer input
266*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
267*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::StatusOr<std::unique_ptr<SchemaStore>> Create(
268*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir,
269*8b6cd535SAndroid Build Coastguard Worker       const Clock* clock, const FeatureFlags* feature_flags,
270*8b6cd535SAndroid Build Coastguard Worker       bool enable_schema_database = false,
271*8b6cd535SAndroid Build Coastguard Worker       InitializeStatsProto* initialize_stats = nullptr);
272*8b6cd535SAndroid Build Coastguard Worker 
273*8b6cd535SAndroid Build Coastguard Worker   // Migrates schema files (backup v.s. new schema) according to version state
274*8b6cd535SAndroid Build Coastguard Worker   // change. Also performs schema database migration and populates the database
275*8b6cd535SAndroid Build Coastguard Worker   // fields in the persisted schema file if necessary.
276*8b6cd535SAndroid Build Coastguard Worker   //
277*8b6cd535SAndroid Build Coastguard Worker   // Returns:
278*8b6cd535SAndroid Build Coastguard Worker   //   OK on success or nothing to migrate
279*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::Status MigrateSchema(
280*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir,
281*8b6cd535SAndroid Build Coastguard Worker       version_util::StateChange version_state_change, int32_t new_version,
282*8b6cd535SAndroid Build Coastguard Worker       bool perform_schema_database_migration);
283*8b6cd535SAndroid Build Coastguard Worker 
284*8b6cd535SAndroid Build Coastguard Worker   // Discards all derived data in the schema store.
285*8b6cd535SAndroid Build Coastguard Worker   //
286*8b6cd535SAndroid Build Coastguard Worker   // Returns:
287*8b6cd535SAndroid Build Coastguard Worker   //   OK on success or nothing to discard
288*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any I/O errors
289*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::Status DiscardDerivedFiles(
290*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir);
291*8b6cd535SAndroid Build Coastguard Worker 
292*8b6cd535SAndroid Build Coastguard Worker   SchemaStore(SchemaStore&&) = default;
293*8b6cd535SAndroid Build Coastguard Worker   SchemaStore& operator=(SchemaStore&&) = default;
294*8b6cd535SAndroid Build Coastguard Worker 
295*8b6cd535SAndroid Build Coastguard Worker   SchemaStore(const SchemaStore&) = delete;
296*8b6cd535SAndroid Build Coastguard Worker   SchemaStore& operator=(const SchemaStore&) = delete;
297*8b6cd535SAndroid Build Coastguard Worker 
298*8b6cd535SAndroid Build Coastguard Worker   // Persists and updates checksum of subcomponents.
299*8b6cd535SAndroid Build Coastguard Worker   ~SchemaStore();
300*8b6cd535SAndroid Build Coastguard Worker 
301*8b6cd535SAndroid Build Coastguard Worker   // Retrieve the current schema if it exists.
302*8b6cd535SAndroid Build Coastguard Worker   //
303*8b6cd535SAndroid Build Coastguard Worker   // Returns:
304*8b6cd535SAndroid Build Coastguard Worker   //   - SchemaProto* if exists
305*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors
306*8b6cd535SAndroid Build Coastguard Worker   //   - NOT_FOUND_ERROR if a schema hasn't been set before
307*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const SchemaProto*> GetSchema() const;
308*8b6cd535SAndroid Build Coastguard Worker 
309*8b6cd535SAndroid Build Coastguard Worker   // Retrieve the current schema for a given database if it exists.
310*8b6cd535SAndroid Build Coastguard Worker   //
311*8b6cd535SAndroid Build Coastguard Worker   // This is an expensive operation. Use GetSchema() when retrieving the entire
312*8b6cd535SAndroid Build Coastguard Worker   // schema, or if there is only a single database in the schema store.
313*8b6cd535SAndroid Build Coastguard Worker   //
314*8b6cd535SAndroid Build Coastguard Worker   // Returns:
315*8b6cd535SAndroid Build Coastguard Worker   //   - SchemaProto* containing only schema types from the database, if exists
316*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors
317*8b6cd535SAndroid Build Coastguard Worker   //   - NOT_FOUND_ERROR if the database doesn't exist in the schema, or if a
318*8b6cd535SAndroid Build Coastguard Worker   //     schema hasn't been set before
319*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaProto> GetSchema(
320*8b6cd535SAndroid Build Coastguard Worker       const std::string& database) const;
321*8b6cd535SAndroid Build Coastguard Worker 
322*8b6cd535SAndroid Build Coastguard Worker   // Update our current schema if it's compatible. Does not accept incompatible
323*8b6cd535SAndroid Build Coastguard Worker   // schema or schema with types from multiple databases. Compatibility rules
324*8b6cd535SAndroid Build Coastguard Worker   // defined by SchemaUtil::ComputeCompatibilityDelta.
325*8b6cd535SAndroid Build Coastguard Worker   //
326*8b6cd535SAndroid Build Coastguard Worker   // The schema types in the new schema proto must all be from a single
327*8b6cd535SAndroid Build Coastguard Worker   // database. Does not support setting schema types across multiple databases
328*8b6cd535SAndroid Build Coastguard Worker   // at once.
329*8b6cd535SAndroid Build Coastguard Worker   //
330*8b6cd535SAndroid Build Coastguard Worker   // If ignore_errors_and_delete_documents is set to true, then incompatible
331*8b6cd535SAndroid Build Coastguard Worker   // schema are allowed and we'll force set the schema, meaning
332*8b6cd535SAndroid Build Coastguard Worker   // SetSchemaResult.success will always be true.
333*8b6cd535SAndroid Build Coastguard Worker   //
334*8b6cd535SAndroid Build Coastguard Worker   // Returns:
335*8b6cd535SAndroid Build Coastguard Worker   //   - SetSchemaResult that encapsulates the differences between the old and
336*8b6cd535SAndroid Build Coastguard Worker   //     new schema, as well as if the new schema can be set.
337*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors
338*8b6cd535SAndroid Build Coastguard Worker   //   - ALREADY_EXISTS_ERROR if type names in the new schema are already in use
339*8b6cd535SAndroid Build Coastguard Worker   //     by a different database.
340*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if the schema is invalid, or if the schema types
341*8b6cd535SAndroid Build Coastguard Worker   //     are from multiple databases (once schema database is enabled).
342*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SetSchemaResult> SetSchema(
343*8b6cd535SAndroid Build Coastguard Worker       const SchemaProto& new_schema, bool ignore_errors_and_delete_documents,
344*8b6cd535SAndroid Build Coastguard Worker       bool allow_circular_schema_definitions);
345*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SetSchemaResult> SetSchema(
346*8b6cd535SAndroid Build Coastguard Worker       SchemaProto&& new_schema, bool ignore_errors_and_delete_documents,
347*8b6cd535SAndroid Build Coastguard Worker       bool allow_circular_schema_definitions);
348*8b6cd535SAndroid Build Coastguard Worker 
349*8b6cd535SAndroid Build Coastguard Worker   // Get the SchemaTypeConfigProto of schema_type name.
350*8b6cd535SAndroid Build Coastguard Worker   //
351*8b6cd535SAndroid Build Coastguard Worker   // Returns:
352*8b6cd535SAndroid Build Coastguard Worker   //   SchemaTypeConfigProto on success
353*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
354*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND if schema type name doesn't exist
355*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL on any I/O errors
356*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const SchemaTypeConfigProto*>
357*8b6cd535SAndroid Build Coastguard Worker   GetSchemaTypeConfig(std::string_view schema_type) const;
358*8b6cd535SAndroid Build Coastguard Worker 
359*8b6cd535SAndroid Build Coastguard Worker   // Get a map contains all schema_type name to its blob property paths.
360*8b6cd535SAndroid Build Coastguard Worker   //
361*8b6cd535SAndroid Build Coastguard Worker   // Returns:
362*8b6cd535SAndroid Build Coastguard Worker   //   A map contains all schema_type name to its blob property paths on success
363*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
364*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL on any I/O errors
365*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<
366*8b6cd535SAndroid Build Coastguard Worker       std::unordered_map<std::string, std::vector<std::string>>>
367*8b6cd535SAndroid Build Coastguard Worker   ConstructBlobPropertyMap() const;
368*8b6cd535SAndroid Build Coastguard Worker 
369*8b6cd535SAndroid Build Coastguard Worker   // Returns the schema type of the passed in SchemaTypeId
370*8b6cd535SAndroid Build Coastguard Worker   //
371*8b6cd535SAndroid Build Coastguard Worker   // Returns:
372*8b6cd535SAndroid Build Coastguard Worker   //   schema type on success
373*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
374*8b6cd535SAndroid Build Coastguard Worker   //   INVALID_ARGUMENT if schema type id is invalid
375*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const std::string*> GetSchemaType(
376*8b6cd535SAndroid Build Coastguard Worker       SchemaTypeId schema_type_id) const;
377*8b6cd535SAndroid Build Coastguard Worker 
378*8b6cd535SAndroid Build Coastguard Worker   // Returns the SchemaTypeId of the passed in schema type
379*8b6cd535SAndroid Build Coastguard Worker   //
380*8b6cd535SAndroid Build Coastguard Worker   // Returns:
381*8b6cd535SAndroid Build Coastguard Worker   //   SchemaTypeId on success
382*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
383*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND_ERROR if we don't know about the schema type
384*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
385*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaTypeId> GetSchemaTypeId(
386*8b6cd535SAndroid Build Coastguard Worker       std::string_view schema_type) const;
387*8b6cd535SAndroid Build Coastguard Worker 
388*8b6cd535SAndroid Build Coastguard Worker   // Similar to GetSchemaTypeId but will return a set of SchemaTypeId to also
389*8b6cd535SAndroid Build Coastguard Worker   // include child types.
390*8b6cd535SAndroid Build Coastguard Worker   //
391*8b6cd535SAndroid Build Coastguard Worker   // Returns:
392*8b6cd535SAndroid Build Coastguard Worker   //   A set of SchemaTypeId on success
393*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
394*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND_ERROR if we don't know about the schema type
395*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
396*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const std::unordered_set<SchemaTypeId>*>
397*8b6cd535SAndroid Build Coastguard Worker   GetSchemaTypeIdsWithChildren(std::string_view schema_type) const;
398*8b6cd535SAndroid Build Coastguard Worker 
399*8b6cd535SAndroid Build Coastguard Worker   // Returns the SectionMetadata associated with the SectionId that's in the
400*8b6cd535SAndroid Build Coastguard Worker   // SchemaTypeId.
401*8b6cd535SAndroid Build Coastguard Worker   //
402*8b6cd535SAndroid Build Coastguard Worker   // Returns:
403*8b6cd535SAndroid Build Coastguard Worker   //   Valid pointer to SectionMetadata on success
404*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
405*8b6cd535SAndroid Build Coastguard Worker   //   INVALID_ARGUMENT if schema type id or section id is invalid
406*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const SectionMetadata*> GetSectionMetadata(
407*8b6cd535SAndroid Build Coastguard Worker       SchemaTypeId schema_type_id, SectionId section_id) const;
408*8b6cd535SAndroid Build Coastguard Worker 
409*8b6cd535SAndroid Build Coastguard Worker   // Returns true if a property is defined in the said schema, regardless of
410*8b6cd535SAndroid Build Coastguard Worker   // whether it is indexed or not.
411*8b6cd535SAndroid Build Coastguard Worker   bool IsPropertyDefinedInSchema(SchemaTypeId schema_type_id,
412*8b6cd535SAndroid Build Coastguard Worker                                  const std::string& property) const;
413*8b6cd535SAndroid Build Coastguard Worker 
414*8b6cd535SAndroid Build Coastguard Worker   // Extracts all sections of different types from the given document and group
415*8b6cd535SAndroid Build Coastguard Worker   // them by type.
416*8b6cd535SAndroid Build Coastguard Worker   // - Each Section vector is sorted by section Id in ascending order. The
417*8b6cd535SAndroid Build Coastguard Worker   //   sorted section ids may not be continuous, since not all sections are
418*8b6cd535SAndroid Build Coastguard Worker   //   present in the document.
419*8b6cd535SAndroid Build Coastguard Worker   // - Sections with empty content won't be returned.
420*8b6cd535SAndroid Build Coastguard Worker   // - For example, we may extract:
421*8b6cd535SAndroid Build Coastguard Worker   //   string_sections: [2, 7, 10]
422*8b6cd535SAndroid Build Coastguard Worker   //   integer_sections: [3, 5, 8]
423*8b6cd535SAndroid Build Coastguard Worker   //
424*8b6cd535SAndroid Build Coastguard Worker   // Returns:
425*8b6cd535SAndroid Build Coastguard Worker   //   A SectionGroup instance on success
426*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
427*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND if type config name of document not found
428*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SectionGroup> ExtractSections(
429*8b6cd535SAndroid Build Coastguard Worker       const DocumentProto& document) const;
430*8b6cd535SAndroid Build Coastguard Worker 
431*8b6cd535SAndroid Build Coastguard Worker   // Returns the JoinablePropertyMetadata associated with property_path that's
432*8b6cd535SAndroid Build Coastguard Worker   // in the SchemaTypeId.
433*8b6cd535SAndroid Build Coastguard Worker   //
434*8b6cd535SAndroid Build Coastguard Worker   // Returns:
435*8b6cd535SAndroid Build Coastguard Worker   //   Valid pointer to JoinablePropertyMetadata on success
436*8b6cd535SAndroid Build Coastguard Worker   //   nullptr if property_path doesn't exist (or is not joinable) in the
437*8b6cd535SAndroid Build Coastguard Worker   //     joinable metadata list of the schema
438*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
439*8b6cd535SAndroid Build Coastguard Worker   //   INVALID_ARGUMENT if schema type id is invalid
440*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const JoinablePropertyMetadata*>
441*8b6cd535SAndroid Build Coastguard Worker   GetJoinablePropertyMetadata(SchemaTypeId schema_type_id,
442*8b6cd535SAndroid Build Coastguard Worker                               const std::string& property_path) const;
443*8b6cd535SAndroid Build Coastguard Worker 
444*8b6cd535SAndroid Build Coastguard Worker   // Returns the JoinablePropertyMetadata associated with joinable_property_id
445*8b6cd535SAndroid Build Coastguard Worker   // that's in the SchemaTypeId.
446*8b6cd535SAndroid Build Coastguard Worker   //
447*8b6cd535SAndroid Build Coastguard Worker   // Returns:
448*8b6cd535SAndroid Build Coastguard Worker   //   Valid pointer to JoinablePropertyMetadata on success
449*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
450*8b6cd535SAndroid Build Coastguard Worker   //   INVALID_ARGUMENT if schema type id or joinable property id is invalid
451*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const JoinablePropertyMetadata*>
452*8b6cd535SAndroid Build Coastguard Worker   GetJoinablePropertyMetadata(SchemaTypeId schema_type_id,
453*8b6cd535SAndroid Build Coastguard Worker                               JoinablePropertyId joinable_property_id) const;
454*8b6cd535SAndroid Build Coastguard Worker 
455*8b6cd535SAndroid Build Coastguard Worker   // Extracts all joinable property contents of different types from the given
456*8b6cd535SAndroid Build Coastguard Worker   // document and group them by joinable value type.
457*8b6cd535SAndroid Build Coastguard Worker   // - Joinable properties are sorted by joinable property id in ascending
458*8b6cd535SAndroid Build Coastguard Worker   //   order. The sorted joinable property ids may not be continuous, since not
459*8b6cd535SAndroid Build Coastguard Worker   //   all joinable properties are present in the document.
460*8b6cd535SAndroid Build Coastguard Worker   // - Joinable property ids start from 0.
461*8b6cd535SAndroid Build Coastguard Worker   // - Joinable properties with empty content won't be returned.
462*8b6cd535SAndroid Build Coastguard Worker   //
463*8b6cd535SAndroid Build Coastguard Worker   // Returns:
464*8b6cd535SAndroid Build Coastguard Worker   //   A JoinablePropertyGroup instance on success
465*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if schema hasn't been set yet
466*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND if the type config name of document not found
467*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<JoinablePropertyGroup> ExtractJoinableProperties(
468*8b6cd535SAndroid Build Coastguard Worker       const DocumentProto& document) const;
469*8b6cd535SAndroid Build Coastguard Worker 
470*8b6cd535SAndroid Build Coastguard Worker   // Returns the quantization type for the given schema_type_id and section_id.
471*8b6cd535SAndroid Build Coastguard Worker   //
472*8b6cd535SAndroid Build Coastguard Worker   // Returns:
473*8b6cd535SAndroid Build Coastguard Worker   //   - The quantization type on success.
474*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if schema_type_id or section_id is invalid.
475*8b6cd535SAndroid Build Coastguard Worker   //   - Any error from schema store.
476*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<EmbeddingIndexingConfig::QuantizationType::Code>
GetQuantizationType(SchemaTypeId schema_type_id,SectionId section_id)477*8b6cd535SAndroid Build Coastguard Worker   GetQuantizationType(SchemaTypeId schema_type_id, SectionId section_id) const {
478*8b6cd535SAndroid Build Coastguard Worker     ICING_ASSIGN_OR_RETURN(const SectionMetadata* section_metadata,
479*8b6cd535SAndroid Build Coastguard Worker                            GetSectionMetadata(schema_type_id, section_id));
480*8b6cd535SAndroid Build Coastguard Worker     return section_metadata->quantization_type;
481*8b6cd535SAndroid Build Coastguard Worker   }
482*8b6cd535SAndroid Build Coastguard Worker 
483*8b6cd535SAndroid Build Coastguard Worker   // Syncs all the data changes to disk.
484*8b6cd535SAndroid Build Coastguard Worker   //
485*8b6cd535SAndroid Build Coastguard Worker   // Returns:
486*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
487*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL on I/O errors.
488*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status PersistToDisk();
489*8b6cd535SAndroid Build Coastguard Worker 
490*8b6cd535SAndroid Build Coastguard Worker   // Recomputes the combined checksum of components of the schema store and
491*8b6cd535SAndroid Build Coastguard Worker   // updates the header.
492*8b6cd535SAndroid Build Coastguard Worker   //
493*8b6cd535SAndroid Build Coastguard Worker   // Returns:
494*8b6cd535SAndroid Build Coastguard Worker   //   - the checksum on success
495*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL on I/O errors.
496*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<Crc32> UpdateChecksum();
497*8b6cd535SAndroid Build Coastguard Worker 
498*8b6cd535SAndroid Build Coastguard Worker   // Recomputes the combined checksum of components of the schema store. Does
499*8b6cd535SAndroid Build Coastguard Worker   // NOT update the header.
500*8b6cd535SAndroid Build Coastguard Worker   //
501*8b6cd535SAndroid Build Coastguard Worker   // Returns:
502*8b6cd535SAndroid Build Coastguard Worker   //   - the checksum on success
503*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL on I/O errors.
504*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<Crc32> GetChecksum() const;
505*8b6cd535SAndroid Build Coastguard Worker 
506*8b6cd535SAndroid Build Coastguard Worker   // Returns:
507*8b6cd535SAndroid Build Coastguard Worker   //   - On success, the section metadata list for the specified schema type
508*8b6cd535SAndroid Build Coastguard Worker   //   - NOT_FOUND if the schema type is not present in the schema
509*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<const std::vector<SectionMetadata>*>
510*8b6cd535SAndroid Build Coastguard Worker   GetSectionMetadata(const std::string& schema_type) const;
511*8b6cd535SAndroid Build Coastguard Worker 
512*8b6cd535SAndroid Build Coastguard Worker   // Gets the index of the given |property_path|, where the index N means that
513*8b6cd535SAndroid Build Coastguard Worker   // it is the Nth scorable property path in the schema config of the given
514*8b6cd535SAndroid Build Coastguard Worker   // |schema_type_id|, in lexicographical order.
515*8b6cd535SAndroid Build Coastguard Worker   //
516*8b6cd535SAndroid Build Coastguard Worker   // Returns:
517*8b6cd535SAndroid Build Coastguard Worker   //   - Index on success
518*8b6cd535SAndroid Build Coastguard Worker   //   - std::nullopt if the |property_path| doesn't point to a scorable
519*8b6cd535SAndroid Build Coastguard Worker   //     property under the |schema_type_id|
520*8b6cd535SAndroid Build Coastguard Worker   //   - FAILED_PRECONDITION if the schema hasn't been set yet
521*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT if |schema_type_id| is invalid
522*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<std::optional<int>> GetScorablePropertyIndex(
523*8b6cd535SAndroid Build Coastguard Worker       SchemaTypeId schema_type_id, std::string_view property_path) const;
524*8b6cd535SAndroid Build Coastguard Worker 
525*8b6cd535SAndroid Build Coastguard Worker   // Returns the list of ScorablePropertyInfo for the given |schema_type_id|,
526*8b6cd535SAndroid Build Coastguard Worker   // in lexicographical order of its property path.
527*8b6cd535SAndroid Build Coastguard Worker   //
528*8b6cd535SAndroid Build Coastguard Worker   // Returns:
529*8b6cd535SAndroid Build Coastguard Worker   //   - Vector of scorable property info on success. The vector can be empty
530*8b6cd535SAndroid Build Coastguard Worker   //     if no scorable property is found under the schema config of
531*8b6cd535SAndroid Build Coastguard Worker   //     |schema_type_id|.
532*8b6cd535SAndroid Build Coastguard Worker   //   - FAILED_PRECONDITION if the schema hasn't been set yet
533*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT if |schema_type_id| is invalid
534*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<
535*8b6cd535SAndroid Build Coastguard Worker       const std::vector<ScorablePropertyManager::ScorablePropertyInfo>*>
536*8b6cd535SAndroid Build Coastguard Worker   GetOrderedScorablePropertyInfo(SchemaTypeId schema_type_id) const;
537*8b6cd535SAndroid Build Coastguard Worker 
538*8b6cd535SAndroid Build Coastguard Worker   // Calculates the StorageInfo for the Schema Store.
539*8b6cd535SAndroid Build Coastguard Worker   //
540*8b6cd535SAndroid Build Coastguard Worker   // If an IO error occurs while trying to calculate the value for a field, then
541*8b6cd535SAndroid Build Coastguard Worker   // that field will be set to -1.
542*8b6cd535SAndroid Build Coastguard Worker   SchemaStoreStorageInfoProto GetStorageInfo() const;
543*8b6cd535SAndroid Build Coastguard Worker 
544*8b6cd535SAndroid Build Coastguard Worker   // Get debug information for the schema store.
545*8b6cd535SAndroid Build Coastguard Worker   //
546*8b6cd535SAndroid Build Coastguard Worker   // Returns:
547*8b6cd535SAndroid Build Coastguard Worker   //   SchemaDebugInfoProto on success
548*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO errors, crc compute error
549*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaDebugInfoProto> GetDebugInfo() const;
550*8b6cd535SAndroid Build Coastguard Worker 
551*8b6cd535SAndroid Build Coastguard Worker   // Expands the provided type_property_masks into a vector of
552*8b6cd535SAndroid Build Coastguard Worker   // ExpandedTypePropertyMasks to account for polymorphism. If both a parent
553*8b6cd535SAndroid Build Coastguard Worker   // type and one of its child type appears in the masks, the parent type's
554*8b6cd535SAndroid Build Coastguard Worker   // paths will be merged into the child's.
555*8b6cd535SAndroid Build Coastguard Worker   //
556*8b6cd535SAndroid Build Coastguard Worker   // For example, assume that we have two schema types A and B, and we have
557*8b6cd535SAndroid Build Coastguard Worker   // - A is the parent type of B
558*8b6cd535SAndroid Build Coastguard Worker   // - Paths of A: {P1, P2}
559*8b6cd535SAndroid Build Coastguard Worker   // - Paths of B: {P3}
560*8b6cd535SAndroid Build Coastguard Worker   //
561*8b6cd535SAndroid Build Coastguard Worker   // Then, we will have the following in the result.
562*8b6cd535SAndroid Build Coastguard Worker   // - Expanded paths of A: {P1, P2}
563*8b6cd535SAndroid Build Coastguard Worker   // - Expanded paths of B: {P1, P2, P3}
564*8b6cd535SAndroid Build Coastguard Worker   std::vector<ExpandedTypePropertyMask> ExpandTypePropertyMasks(
565*8b6cd535SAndroid Build Coastguard Worker       const google::protobuf::RepeatedPtrField<TypePropertyMask>& type_property_masks)
566*8b6cd535SAndroid Build Coastguard Worker       const;
567*8b6cd535SAndroid Build Coastguard Worker 
568*8b6cd535SAndroid Build Coastguard Worker  private:
569*8b6cd535SAndroid Build Coastguard Worker   // Factory function to create a SchemaStore and set its schema. The created
570*8b6cd535SAndroid Build Coastguard Worker   // instance does not take ownership of any input components and all pointers
571*8b6cd535SAndroid Build Coastguard Worker   // must refer to valid objects that outlive the created SchemaStore instance.
572*8b6cd535SAndroid Build Coastguard Worker   // The base_dir must already exist. No schema must have set in base_dir prior
573*8b6cd535SAndroid Build Coastguard Worker   // to this.
574*8b6cd535SAndroid Build Coastguard Worker   //
575*8b6cd535SAndroid Build Coastguard Worker   // Returns:
576*8b6cd535SAndroid Build Coastguard Worker   //   A SchemaStore on success
577*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION on any null pointer input or if there has already
578*8b6cd535SAndroid Build Coastguard Worker   //       been a schema set for this path.
579*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
580*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::StatusOr<std::unique_ptr<SchemaStore>> Create(
581*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir,
582*8b6cd535SAndroid Build Coastguard Worker       const Clock* clock, const FeatureFlags* feature_flags, SchemaProto schema,
583*8b6cd535SAndroid Build Coastguard Worker       bool enable_schema_database);
584*8b6cd535SAndroid Build Coastguard Worker 
585*8b6cd535SAndroid Build Coastguard Worker   // Use SchemaStore::Create instead.
586*8b6cd535SAndroid Build Coastguard Worker   explicit SchemaStore(const Filesystem* filesystem, std::string base_dir,
587*8b6cd535SAndroid Build Coastguard Worker                        const Clock* clock, const FeatureFlags* feature_flags,
588*8b6cd535SAndroid Build Coastguard Worker                        bool enable_schema_database);
589*8b6cd535SAndroid Build Coastguard Worker 
590*8b6cd535SAndroid Build Coastguard Worker   // Deletes the overlay schema and ensures that the Header is correctly set.
591*8b6cd535SAndroid Build Coastguard Worker   //
592*8b6cd535SAndroid Build Coastguard Worker   // RETURNS:
593*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
594*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
595*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::Status DiscardOverlaySchema(
596*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir,
597*8b6cd535SAndroid Build Coastguard Worker       Header& header);
598*8b6cd535SAndroid Build Coastguard Worker 
599*8b6cd535SAndroid Build Coastguard Worker   // Handles the overlay schema after a version change by deleting it if it is
600*8b6cd535SAndroid Build Coastguard Worker   // no longer compatible with the new version.
601*8b6cd535SAndroid Build Coastguard Worker   //
602*8b6cd535SAndroid Build Coastguard Worker   // Requires: base_dir exists.
603*8b6cd535SAndroid Build Coastguard Worker   //
604*8b6cd535SAndroid Build Coastguard Worker   // Returns:
605*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
606*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
607*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::Status HandleOverlaySchemaForVersionChange(
608*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& base_dir,
609*8b6cd535SAndroid Build Coastguard Worker       version_util::StateChange version_state_change, int32_t new_version);
610*8b6cd535SAndroid Build Coastguard Worker 
611*8b6cd535SAndroid Build Coastguard Worker   // Populates the schema database field in the schema proto that is stored in
612*8b6cd535SAndroid Build Coastguard Worker   // the input schema file.
613*8b6cd535SAndroid Build Coastguard Worker   //
614*8b6cd535SAndroid Build Coastguard Worker   // Returns:
615*8b6cd535SAndroid Build Coastguard Worker   //   OK on success or nothing to migrate
616*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
617*8b6cd535SAndroid Build Coastguard Worker   static libtextclassifier3::Status PopulateSchemaDatabaseFieldForSchemaFile(
618*8b6cd535SAndroid Build Coastguard Worker       const Filesystem* filesystem, const std::string& schema_filename);
619*8b6cd535SAndroid Build Coastguard Worker 
620*8b6cd535SAndroid Build Coastguard Worker   // Verifies that there is no error retrieving a previously set schema. Then
621*8b6cd535SAndroid Build Coastguard Worker   // initializes like normal.
622*8b6cd535SAndroid Build Coastguard Worker   //
623*8b6cd535SAndroid Build Coastguard Worker   // Returns:
624*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
625*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
626*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status Initialize(InitializeStatsProto* initialize_stats);
627*8b6cd535SAndroid Build Coastguard Worker 
628*8b6cd535SAndroid Build Coastguard Worker   // First, blindly writes new_schema to the schema_file. Then initializes like
629*8b6cd535SAndroid Build Coastguard Worker   // normal.
630*8b6cd535SAndroid Build Coastguard Worker   //
631*8b6cd535SAndroid Build Coastguard Worker   // Returns:
632*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
633*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
634*8b6cd535SAndroid Build Coastguard Worker   //   FAILED_PRECONDITION if there is already a schema set for the schema_file.
635*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status Initialize(SchemaProto new_schema);
636*8b6cd535SAndroid Build Coastguard Worker 
637*8b6cd535SAndroid Build Coastguard Worker   // Handles initializing the SchemaStore and regenerating any data if needed.
638*8b6cd535SAndroid Build Coastguard Worker   //
639*8b6cd535SAndroid Build Coastguard Worker   // Returns:
640*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
641*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
642*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status InitializeInternal(
643*8b6cd535SAndroid Build Coastguard Worker       bool create_overlay_if_necessary, InitializeStatsProto* initialize_stats);
644*8b6cd535SAndroid Build Coastguard Worker 
645*8b6cd535SAndroid Build Coastguard Worker   // Creates sub-components and verifies the integrity of each sub-component.
646*8b6cd535SAndroid Build Coastguard Worker   //
647*8b6cd535SAndroid Build Coastguard Worker   // Returns:
648*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
649*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on IO error
650*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status InitializeDerivedFiles();
651*8b6cd535SAndroid Build Coastguard Worker 
652*8b6cd535SAndroid Build Coastguard Worker   // Populates any derived data structures off of the schema.
653*8b6cd535SAndroid Build Coastguard Worker   //
654*8b6cd535SAndroid Build Coastguard Worker   // Returns:
655*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
656*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND_ERROR if a schema proto has not been set
657*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
658*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status RegenerateDerivedFiles(
659*8b6cd535SAndroid Build Coastguard Worker       bool create_overlay_if_necessary);
660*8b6cd535SAndroid Build Coastguard Worker 
661*8b6cd535SAndroid Build Coastguard Worker   // Build type_config_map_, schema_subtype_id_map_, and schema_type_manager_.
662*8b6cd535SAndroid Build Coastguard Worker   //
663*8b6cd535SAndroid Build Coastguard Worker   // Returns:
664*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
665*8b6cd535SAndroid Build Coastguard Worker   //   NOT_FOUND_ERROR if a schema proto has not been set
666*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL_ERROR on any IO errors
667*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status BuildInMemoryCache();
668*8b6cd535SAndroid Build Coastguard Worker 
669*8b6cd535SAndroid Build Coastguard Worker   // Update and replace the header file. Creates the header file if it doesn't
670*8b6cd535SAndroid Build Coastguard Worker   // exist.
671*8b6cd535SAndroid Build Coastguard Worker   //
672*8b6cd535SAndroid Build Coastguard Worker   // Returns:
673*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
674*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL on I/O error
675*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status UpdateHeader(const Crc32& checksum);
676*8b6cd535SAndroid Build Coastguard Worker 
677*8b6cd535SAndroid Build Coastguard Worker   // Resets the unique_ptr to the schema_type_mapper_, deletes the underlying
678*8b6cd535SAndroid Build Coastguard Worker   // file, and re-creates a new instance of the schema_type_mapper_. Does not
679*8b6cd535SAndroid Build Coastguard Worker   // populate the schema_type_mapper_.
680*8b6cd535SAndroid Build Coastguard Worker   //
681*8b6cd535SAndroid Build Coastguard Worker   // Returns any IO errors.
682*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status ResetSchemaTypeMapper();
683*8b6cd535SAndroid Build Coastguard Worker 
684*8b6cd535SAndroid Build Coastguard Worker   // Creates a new schema store with new_schema and then swaps that new schema
685*8b6cd535SAndroid Build Coastguard Worker   // store with the existing one. This function guarantees that either: this
686*8b6cd535SAndroid Build Coastguard Worker   // instance will be fully updated to the new schema or no changes will take
687*8b6cd535SAndroid Build Coastguard Worker   // effect.
688*8b6cd535SAndroid Build Coastguard Worker   //
689*8b6cd535SAndroid Build Coastguard Worker   // Returns:
690*8b6cd535SAndroid Build Coastguard Worker   //   OK on success
691*8b6cd535SAndroid Build Coastguard Worker   //   INTERNAL on I/O error.
692*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status ApplySchemaChange(SchemaProto new_schema);
693*8b6cd535SAndroid Build Coastguard Worker 
CheckSchemaSet()694*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status CheckSchemaSet() const {
695*8b6cd535SAndroid Build Coastguard Worker     return has_schema_successfully_set_
696*8b6cd535SAndroid Build Coastguard Worker                ? libtextclassifier3::Status::OK
697*8b6cd535SAndroid Build Coastguard Worker                : absl_ports::FailedPreconditionError("Schema not set yet.");
698*8b6cd535SAndroid Build Coastguard Worker   }
699*8b6cd535SAndroid Build Coastguard Worker 
700*8b6cd535SAndroid Build Coastguard Worker   // Correctly loads the Header, schema_file_ and (if present) the
701*8b6cd535SAndroid Build Coastguard Worker   // overlay_schema_file_.
702*8b6cd535SAndroid Build Coastguard Worker   // RETURNS:
703*8b6cd535SAndroid Build Coastguard Worker   //   - OK on success
704*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL if an IO error is encountered when reading the Header or
705*8b6cd535SAndroid Build Coastguard Worker   //   schemas.
706*8b6cd535SAndroid Build Coastguard Worker   //     Or an invalid schema configuration is present.
707*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::Status LoadSchema();
708*8b6cd535SAndroid Build Coastguard Worker 
709*8b6cd535SAndroid Build Coastguard Worker   // Sets the schema for a database for the first time.
710*8b6cd535SAndroid Build Coastguard Worker   //
711*8b6cd535SAndroid Build Coastguard Worker   // Note that when schema database is disabled, this function sets the entire
712*8b6cd535SAndroid Build Coastguard Worker   // schema, with all under the default empty database.
713*8b6cd535SAndroid Build Coastguard Worker   //
714*8b6cd535SAndroid Build Coastguard Worker   // Requires:
715*8b6cd535SAndroid Build Coastguard Worker   //   - All types in new_schema are from the same database.
716*8b6cd535SAndroid Build Coastguard Worker   //   - new_schema does not contain type names that are already in use by a
717*8b6cd535SAndroid Build Coastguard Worker   //     different database.
718*8b6cd535SAndroid Build Coastguard Worker   //
719*8b6cd535SAndroid Build Coastguard Worker   // Returns:
720*8b6cd535SAndroid Build Coastguard Worker   //   - SetSchemaResult that indicates if the new schema can be set.
721*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors.
722*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if the schema is invalid.
723*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaStore::SetSchemaResult>
724*8b6cd535SAndroid Build Coastguard Worker   SetInitialSchemaForDatabase(SchemaProto new_schema,
725*8b6cd535SAndroid Build Coastguard Worker                               bool ignore_errors_and_delete_documents,
726*8b6cd535SAndroid Build Coastguard Worker                               bool allow_circular_schema_definitions);
727*8b6cd535SAndroid Build Coastguard Worker 
728*8b6cd535SAndroid Build Coastguard Worker   // Sets the schema for a database, overriding any existing schema for that
729*8b6cd535SAndroid Build Coastguard Worker   // database.
730*8b6cd535SAndroid Build Coastguard Worker   //
731*8b6cd535SAndroid Build Coastguard Worker   // Note that when schema database is disabled, this function sets and
732*8b6cd535SAndroid Build Coastguard Worker   // overrides the entire schema.
733*8b6cd535SAndroid Build Coastguard Worker   //
734*8b6cd535SAndroid Build Coastguard Worker   // Requires:
735*8b6cd535SAndroid Build Coastguard Worker   //   - All types in new_schema are from the same database.
736*8b6cd535SAndroid Build Coastguard Worker   //   - new_schema does not contain type names that are already in use by a
737*8b6cd535SAndroid Build Coastguard Worker   //     different database.
738*8b6cd535SAndroid Build Coastguard Worker   //
739*8b6cd535SAndroid Build Coastguard Worker   // Returns:
740*8b6cd535SAndroid Build Coastguard Worker   //   - SetSchemaResult that encapsulates the differences between the old and
741*8b6cd535SAndroid Build Coastguard Worker   //     new schema, as well as if the new schema can be set.
742*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors.
743*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if the schema is invalid.
744*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaStore::SetSchemaResult>
745*8b6cd535SAndroid Build Coastguard Worker   SetSchemaWithDatabaseOverride(SchemaProto new_schema,
746*8b6cd535SAndroid Build Coastguard Worker                                 const SchemaProto& old_schema,
747*8b6cd535SAndroid Build Coastguard Worker                                 bool ignore_errors_and_delete_documents,
748*8b6cd535SAndroid Build Coastguard Worker                                 bool allow_circular_schema_definitions);
749*8b6cd535SAndroid Build Coastguard Worker 
750*8b6cd535SAndroid Build Coastguard Worker   // Initial validation on the SchemaProto for SetSchema. This is intended as a
751*8b6cd535SAndroid Build Coastguard Worker   // preliminary check before any expensive operations are performed during
752*8b6cd535SAndroid Build Coastguard Worker   // `SetSchema::Validate`. Returns the schema's database if it's valid.
753*8b6cd535SAndroid Build Coastguard Worker   //
754*8b6cd535SAndroid Build Coastguard Worker   // Note that when schema database is disabled, any schema input is valid and
755*8b6cd535SAndroid Build Coastguard Worker   // an empty string is returned as the database.
756*8b6cd535SAndroid Build Coastguard Worker   //
757*8b6cd535SAndroid Build Coastguard Worker   // Checks that:
758*8b6cd535SAndroid Build Coastguard Worker   // - The new schema only contains types from a single database.
759*8b6cd535SAndroid Build Coastguard Worker   // - The schema's type names are not already in use in other databases. This
760*8b6cd535SAndroid Build Coastguard Worker   //   is done outside of `SchemaUtil::Validate` because we need to know all
761*8b6cd535SAndroid Build Coastguard Worker   //   existing type names, which is stored in the SchemaStore and not known to
762*8b6cd535SAndroid Build Coastguard Worker   //   SchemaUtil.
763*8b6cd535SAndroid Build Coastguard Worker   //
764*8b6cd535SAndroid Build Coastguard Worker   // Returns:
765*8b6cd535SAndroid Build Coastguard Worker   //   - new_schema's database on success
766*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if new_schema contains types from multiple
767*8b6cd535SAndroid Build Coastguard Worker   //     databases
768*8b6cd535SAndroid Build Coastguard Worker   //   - ALREADY_EXISTS_ERROR if new_schema's types names are not unique
769*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<std::string> ValidateAndGetDatabase(
770*8b6cd535SAndroid Build Coastguard Worker       const SchemaProto& new_schema) const;
771*8b6cd535SAndroid Build Coastguard Worker 
772*8b6cd535SAndroid Build Coastguard Worker   // Returns a SchemaProto representing the full schema, which is a combination
773*8b6cd535SAndroid Build Coastguard Worker   // of the existing schema and the input database schema.
774*8b6cd535SAndroid Build Coastguard Worker   //
775*8b6cd535SAndroid Build Coastguard Worker   // For the database being updated by the input database schema:
776*8b6cd535SAndroid Build Coastguard Worker   // - If the existing schema does not contain the database, the input types
777*8b6cd535SAndroid Build Coastguard Worker   //   are appended to the end of the SchemaProto, without changing the order
778*8b6cd535SAndroid Build Coastguard Worker   //   of the existing schema types.
779*8b6cd535SAndroid Build Coastguard Worker   // - Otherwise, the existing schema types are replaced with types from the
780*8b6cd535SAndroid Build Coastguard Worker   //   input database schema in their original position in the existing
781*8b6cd535SAndroid Build Coastguard Worker   //   SchemaProto.
782*8b6cd535SAndroid Build Coastguard Worker   //   - Types from input_database_schema are added in the order in which they
783*8b6cd535SAndroid Build Coastguard Worker   //     appear.
784*8b6cd535SAndroid Build Coastguard Worker   //   - If more types are added to the database, the additional types are
785*8b6cd535SAndroid Build Coastguard Worker   //     appended at the end of the SchemaProto, without changing the order of
786*8b6cd535SAndroid Build Coastguard Worker   //     existing types from unaffected databases.
787*8b6cd535SAndroid Build Coastguard Worker   //
788*8b6cd535SAndroid Build Coastguard Worker   // Requires:
789*8b6cd535SAndroid Build Coastguard Worker   //   - input_database_schema must not contain types from multiple databases.
790*8b6cd535SAndroid Build Coastguard Worker   //
791*8b6cd535SAndroid Build Coastguard Worker   // Returns:
792*8b6cd535SAndroid Build Coastguard Worker   //   - SchemaProto on success
793*8b6cd535SAndroid Build Coastguard Worker   //   - INTERNAL_ERROR on any IO errors, or if the schema store was not
794*8b6cd535SAndroid Build Coastguard Worker   //     previously initialized properly.
795*8b6cd535SAndroid Build Coastguard Worker   //   - INVALID_ARGUMENT_ERROR if the input schema contains types from multiple
796*8b6cd535SAndroid Build Coastguard Worker   //     databases.
797*8b6cd535SAndroid Build Coastguard Worker   libtextclassifier3::StatusOr<SchemaProto> GetFullSchemaProtoWithUpdatedDb(
798*8b6cd535SAndroid Build Coastguard Worker       SchemaProto input_database_schema) const;
799*8b6cd535SAndroid Build Coastguard Worker 
800*8b6cd535SAndroid Build Coastguard Worker   const Filesystem* filesystem_;
801*8b6cd535SAndroid Build Coastguard Worker   std::string base_dir_;
802*8b6cd535SAndroid Build Coastguard Worker   const Clock* clock_;
803*8b6cd535SAndroid Build Coastguard Worker   const FeatureFlags* feature_flags_;  // Does not own.
804*8b6cd535SAndroid Build Coastguard Worker 
805*8b6cd535SAndroid Build Coastguard Worker   // Used internally to indicate whether the class has been successfully
806*8b6cd535SAndroid Build Coastguard Worker   // initialized with a valid schema. Will be false if Initialize failed or no
807*8b6cd535SAndroid Build Coastguard Worker   // schema has ever been set.
808*8b6cd535SAndroid Build Coastguard Worker   bool has_schema_successfully_set_ = false;
809*8b6cd535SAndroid Build Coastguard Worker 
810*8b6cd535SAndroid Build Coastguard Worker   // Cached schema
811*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<FileBackedProto<SchemaProto>> schema_file_;
812*8b6cd535SAndroid Build Coastguard Worker 
813*8b6cd535SAndroid Build Coastguard Worker   // This schema holds the definition of any schema types that are not
814*8b6cd535SAndroid Build Coastguard Worker   // compatible with older versions of Icing code.
815*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<FileBackedProto<SchemaProto>> overlay_schema_file_;
816*8b6cd535SAndroid Build Coastguard Worker 
817*8b6cd535SAndroid Build Coastguard Worker   // Maps schema types to a densely-assigned unique id.
818*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<KeyMapper<SchemaTypeId>> schema_type_mapper_;
819*8b6cd535SAndroid Build Coastguard Worker 
820*8b6cd535SAndroid Build Coastguard Worker   // Maps schema type ids to the corresponding schema type. This is an inverse
821*8b6cd535SAndroid Build Coastguard Worker   // map of schema_type_mapper_.
822*8b6cd535SAndroid Build Coastguard Worker   std::unordered_map<SchemaTypeId, std::string> reverse_schema_type_mapper_;
823*8b6cd535SAndroid Build Coastguard Worker 
824*8b6cd535SAndroid Build Coastguard Worker   // A hash map of (database -> vector of type config names in the database).
825*8b6cd535SAndroid Build Coastguard Worker   //
826*8b6cd535SAndroid Build Coastguard Worker   // We use a vector instead of a set because we need to preserve the order of
827*8b6cd535SAndroid Build Coastguard Worker   // the types (i.e. the order in which they appear in the input SchemaProto
828*8b6cd535SAndroid Build Coastguard Worker   // during SetSchema), so that we can return the correct SchemaProto for
829*8b6cd535SAndroid Build Coastguard Worker   // GetSchema.
830*8b6cd535SAndroid Build Coastguard Worker   //
831*8b6cd535SAndroid Build Coastguard Worker   // This keeps track of the type configs defined in each database, which allows
832*8b6cd535SAndroid Build Coastguard Worker   // schema operations to be performed on a per-database basis.
833*8b6cd535SAndroid Build Coastguard Worker   std::unordered_map<std::string, std::vector<std::string>> database_type_map_;
834*8b6cd535SAndroid Build Coastguard Worker 
835*8b6cd535SAndroid Build Coastguard Worker   // A hash map of (type config name -> type config), allows faster lookup of
836*8b6cd535SAndroid Build Coastguard Worker   // type config in schema. The O(1) type config access makes schema-related and
837*8b6cd535SAndroid Build Coastguard Worker   // section-related operations faster.
838*8b6cd535SAndroid Build Coastguard Worker   SchemaUtil::TypeConfigMap type_config_map_;
839*8b6cd535SAndroid Build Coastguard Worker 
840*8b6cd535SAndroid Build Coastguard Worker   // Maps from each type id to all of its subtype ids.
841*8b6cd535SAndroid Build Coastguard Worker   // T2 is a subtype of T1, if and only if one of the following conditions is
842*8b6cd535SAndroid Build Coastguard Worker   // met:
843*8b6cd535SAndroid Build Coastguard Worker   // - T2 is T1
844*8b6cd535SAndroid Build Coastguard Worker   // - T2 extends T1
845*8b6cd535SAndroid Build Coastguard Worker   // - There exists a type U, such that T2 is a subtype of U, and U is a subtype
846*8b6cd535SAndroid Build Coastguard Worker   //   of T1
847*8b6cd535SAndroid Build Coastguard Worker   std::unordered_map<SchemaTypeId, std::unordered_set<SchemaTypeId>>
848*8b6cd535SAndroid Build Coastguard Worker       schema_subtype_id_map_;
849*8b6cd535SAndroid Build Coastguard Worker 
850*8b6cd535SAndroid Build Coastguard Worker   // Manager of section (indexable property) and joinable property related
851*8b6cd535SAndroid Build Coastguard Worker   // metadata for all Schemas.
852*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<const SchemaTypeManager> schema_type_manager_;
853*8b6cd535SAndroid Build Coastguard Worker 
854*8b6cd535SAndroid Build Coastguard Worker   // Used to cache and manage the schema's scorable properties.
855*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<ScorablePropertyManager> scorable_property_manager_;
856*8b6cd535SAndroid Build Coastguard Worker 
857*8b6cd535SAndroid Build Coastguard Worker   std::unique_ptr<Header> header_;
858*8b6cd535SAndroid Build Coastguard Worker 
859*8b6cd535SAndroid Build Coastguard Worker   // Whether to use the database field for the schema.
860*8b6cd535SAndroid Build Coastguard Worker   //
861*8b6cd535SAndroid Build Coastguard Worker   // This is a temporary flag to control the rollout of the schema database. It
862*8b6cd535SAndroid Build Coastguard Worker   // affects the `SetSchema` and `GetSchema(std::string database)` methods.
863*8b6cd535SAndroid Build Coastguard Worker   // TODO - b/337913932: Remove this flag once the schema database is fully
864*8b6cd535SAndroid Build Coastguard Worker   // rolled out.
865*8b6cd535SAndroid Build Coastguard Worker   bool enable_schema_database_ = false;
866*8b6cd535SAndroid Build Coastguard Worker };
867*8b6cd535SAndroid Build Coastguard Worker 
868*8b6cd535SAndroid Build Coastguard Worker }  // namespace lib
869*8b6cd535SAndroid Build Coastguard Worker }  // namespace icing
870*8b6cd535SAndroid Build Coastguard Worker 
871*8b6cd535SAndroid Build Coastguard Worker #endif  // ICING_SCHEMA_SCHEMA_STORE_H_
872