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 #ifndef ICING_SCHEMA_JOINABLE_PROPERTY_H_
16 #define ICING_SCHEMA_JOINABLE_PROPERTY_H_
17
18 #include <cstdint>
19 #include <string>
20 #include <string_view>
21 #include <utility>
22 #include <vector>
23
24 #include "icing/proto/schema.pb.h"
25
26 namespace icing {
27 namespace lib {
28
29 using JoinablePropertyId = int8_t;
30
31 // 6 bits for 64 values.
32 inline constexpr int kJoinablePropertyIdBits = 6;
33 inline constexpr JoinablePropertyId kTotalNumJoinableProperties =
34 (INT8_C(1) << kJoinablePropertyIdBits);
35 inline constexpr JoinablePropertyId kInvalidJoinablePropertyId =
36 kTotalNumJoinableProperties;
37 inline constexpr JoinablePropertyId kMaxJoinablePropertyId =
38 kTotalNumJoinableProperties - 1;
39 inline constexpr JoinablePropertyId kMinJoinablePropertyId = 0;
40
IsJoinablePropertyIdValid(JoinablePropertyId joinable_property_id)41 constexpr bool IsJoinablePropertyIdValid(
42 JoinablePropertyId joinable_property_id) {
43 return joinable_property_id >= kMinJoinablePropertyId &&
44 joinable_property_id <= kMaxJoinablePropertyId;
45 }
46
47 static_assert(
48 kJoinablePropertyIdBits < 8 * sizeof(JoinablePropertyId),
49 "Cannot exhaust all bits of JoinablePropertyId since it is a signed "
50 "integer and the most significant bit should be preserved.");
51
52 struct JoinablePropertyMetadata {
53 // Dot-joined property names, representing the location of joinable property
54 // inside an document. E.g. "property1.property2".
55 std::string path;
56
57 // A unique id of joinable property.
58 JoinablePropertyId id;
59
60 // Data type of this joinable property values. Currently we only support
61 // STRING.
62 PropertyConfigProto::DataType::Code data_type;
63
64 // How values will be used as a joining matcher.
65 //
66 // JoinableConfig::ValueType::QUALIFIED_ID:
67 // Value in this property is a joinable (string) qualified id. Qualified id
68 // is composed of namespace and uri, and it will be used as the identifier
69 // of the parent document. Note: it is invalid to use this value type with
70 // non-string DataType.
71 JoinableConfig::ValueType::Code value_type;
72
73 // How to propagate the deletion between the document and the referenced
74 // joinable document.
75 //
76 // JoinableConfig::DeletePropagationType::NONE:
77 // No propagation.
78 //
79 // JoinableConfig::DeletePropagationType::PROPAGATE_FROM:
80 // Delete the document when the referenced (parent) document is deleted.
81 //
82 // This is only applicable to joinable properties with value type
83 // JoinableConfig::ValueType::QUALIFIED_ID.
84 JoinableConfig::DeletePropagationType::Code delete_propagation_type;
85
JoinablePropertyMetadataJoinablePropertyMetadata86 explicit JoinablePropertyMetadata(
87 JoinablePropertyId id_in,
88 PropertyConfigProto::DataType::Code data_type_in,
89 JoinableConfig::ValueType::Code value_type_in,
90 JoinableConfig::DeletePropagationType::Code delete_propagation_type_in,
91 std::string&& path_in)
92 : path(std::move(path_in)),
93 id(id_in),
94 data_type(data_type_in),
95 value_type(value_type_in),
96 delete_propagation_type(delete_propagation_type_in) {}
97
98 JoinablePropertyMetadata(const JoinablePropertyMetadata& other) = default;
99 JoinablePropertyMetadata& operator=(const JoinablePropertyMetadata& other) =
100 default;
101
102 JoinablePropertyMetadata(JoinablePropertyMetadata&& other) = default;
103 JoinablePropertyMetadata& operator=(JoinablePropertyMetadata&& other) =
104 default;
105
106 bool operator==(const JoinablePropertyMetadata& rhs) const {
107 return path == rhs.path && id == rhs.id && data_type == rhs.data_type &&
108 value_type == rhs.value_type &&
109 delete_propagation_type == rhs.delete_propagation_type;
110 }
111 };
112
113 // JoinableProperty is an icing internal concept similar to document property
114 // values (contents), but with extra metadata. the data type of value is
115 // specified by template.
116 //
117 // Current supported data types:
118 // - std::string_view (PropertyConfigProto::DataType::STRING)
119 template <typename T>
120 struct JoinableProperty {
121 JoinablePropertyMetadata metadata;
122 std::vector<T> values;
123
JoinablePropertyJoinableProperty124 explicit JoinableProperty(JoinablePropertyMetadata&& metadata_in,
125 std::vector<T>&& values_in)
126 : metadata(std::move(metadata_in)), values(std::move(values_in)) {}
127
data_typeJoinableProperty128 PropertyConfigProto::DataType::Code data_type() const {
129 return metadata.data_type;
130 }
131
value_typeJoinableProperty132 JoinableConfig::ValueType::Code value_type() const {
133 return metadata.value_type;
134 }
135
delete_propagation_typeJoinableProperty136 JoinableConfig::DeletePropagationType::Code delete_propagation_type() const {
137 return metadata.delete_propagation_type;
138 }
139 };
140
141 // Groups of different type joinable properties. Callers can access joinable
142 // properties with types they want and avoid going through non-desired ones.
143 //
144 // REQUIRES: lifecycle of the property must be longer than this object, since we
145 // use std::string_view for extracting its string_values.
146 struct JoinablePropertyGroup {
147 std::vector<JoinableProperty<std::string_view>> qualified_id_properties;
148 };
149
150 } // namespace lib
151 } // namespace icing
152
153 #endif // ICING_SCHEMA_JOINABLE_PROPERTY_H_
154