dpp/data_contract/v1/methods/
schema.rs1use crate::data_contract::accessors::v0::DataContractV0Getters;
2use crate::data_contract::accessors::v1::DataContractV1Getters;
3use crate::data_contract::document_type::accessors::DocumentTypeV0Getters;
4use crate::data_contract::document_type::class_methods::{
5 resolve_derived_index_properties, validate_preallocated_indexes_kept_on_removal,
6 validate_summable_off_count_indexes_lossless,
7};
8use crate::data_contract::document_type::DocumentType;
9use crate::data_contract::schema::DataContractSchemaMethodsV0;
10use crate::data_contract::{DataContractV1, DefinitionName, DocumentName};
11use crate::validation::operations::ProtocolValidationOperation;
12use crate::ProtocolError;
13use platform_value::Value;
14use platform_version::version::PlatformVersion;
15use std::collections::BTreeMap;
16
17impl DataContractSchemaMethodsV0 for DataContractV1 {
18 fn set_document_schemas(
19 &mut self,
20 schemas: BTreeMap<DocumentName, Value>,
21 defs: Option<BTreeMap<DefinitionName, Value>>,
22 full_validation: bool,
23 validation_operations: &mut Vec<ProtocolValidationOperation>,
24 platform_version: &PlatformVersion,
25 ) -> Result<(), ProtocolError> {
26 self.document_types = DocumentType::create_document_types_from_document_schemas(
27 self.id,
28 self.system_version_type(),
29 self.config.version(),
30 schemas,
31 defs.as_ref(),
32 &self.tokens,
33 &self.config,
34 full_validation,
35 !self.tokens.is_empty(),
36 validation_operations,
37 platform_version,
38 )?;
39
40 Ok(())
41 }
42
43 fn set_document_schema(
44 &mut self,
45 name: &str,
46 schema: Value,
47 full_validation: bool,
48 validation_operations: &mut Vec<ProtocolValidationOperation>,
49 platform_version: &PlatformVersion,
50 ) -> Result<(), ProtocolError> {
51 let document_type = DocumentType::try_from_schema(
52 self.id,
53 self.system_version_type(),
54 self.config.version(),
55 name,
56 schema,
57 self.schema_defs.as_ref(),
58 self.tokens(),
59 &self.config,
60 full_validation,
61 validation_operations,
62 platform_version,
63 )?;
64
65 self.document_types
66 .insert(document_type.name().clone(), document_type);
67
68 let data_contract_system_version = self.system_version_type();
73 let contract_config_version = self.config.version();
74 resolve_derived_index_properties(
75 &mut self.document_types,
76 data_contract_system_version,
77 contract_config_version,
78 false,
79 platform_version,
80 )?;
81 if full_validation {
85 validate_preallocated_indexes_kept_on_removal(&self.document_types)?;
86 validate_summable_off_count_indexes_lossless(&self.document_types)?;
90 }
91
92 Ok(())
93 }
94
95 fn document_schemas(&self) -> BTreeMap<DocumentName, &Value> {
96 self.document_types
97 .iter()
98 .map(|(name, document_type)| (name.to_owned(), document_type.schema()))
99 .collect()
100 }
101
102 fn schema_defs(&self) -> Option<&BTreeMap<DefinitionName, Value>> {
103 self.schema_defs.as_ref()
104 }
105
106 fn set_schema_defs(
107 &mut self,
108 defs: Option<BTreeMap<DefinitionName, Value>>,
109 full_validation: bool,
110 validation_operations: &mut Vec<ProtocolValidationOperation>,
111 platform_version: &PlatformVersion,
112 ) -> Result<(), ProtocolError> {
113 let document_schemas = self
114 .document_types
115 .iter()
116 .map(|(name, document_type)| (name.to_owned(), document_type.schema().to_owned()))
117 .collect();
118
119 self.set_document_schemas(
120 document_schemas,
121 defs.clone(),
122 full_validation,
123 validation_operations,
124 platform_version,
125 )?;
126
127 self.schema_defs = defs;
128
129 Ok(())
130 }
131}
132
133#[cfg(test)]
134mod test {
135 use super::*;
136 use crate::data_contract::config::DataContractConfig;
137 use crate::data_contract::serialized_version::v0::DataContractInSerializationFormatV0;
138 use crate::data_contract::v1::DataContractV1;
139 use platform_value::{platform_value, Identifier};
140
141 #[test]
142 fn should_set_a_new_schema_defs() {
143 let platform_version = PlatformVersion::latest();
144
145 let config = DataContractConfig::default_for_version(platform_version)
146 .expect("should create a default config");
147
148 let schema = platform_value!({
149 "type": "object",
150 "properties": {
151 "a": {
152 "type": "string",
153 "maxLength": 10,
154 "position": 0
155 }
156 },
157 "additionalProperties": false,
158 });
159
160 let serialization_format = DataContractInSerializationFormatV0 {
161 id: Identifier::random(),
162 config,
163 version: 0,
164 owner_id: Default::default(),
165 schema_defs: None,
166 document_schemas: BTreeMap::from([("document_type_name".to_string(), schema.clone())]),
167 };
168
169 let mut data_contract = DataContractV1::try_from_platform_versioned(
170 serialization_format.into(),
171 true,
172 &mut vec![],
173 platform_version,
174 )
175 .expect("should create a contract from serialization format");
176
177 let defs = platform_value!({
178 "test": {
179 "type": "string",
180 },
181 });
182
183 let defs_map = Some(defs.into_btree_string_map().expect("should convert to map"));
184
185 data_contract
186 .set_schema_defs(defs_map.clone(), true, &mut vec![], platform_version)
187 .expect("should set defs");
188
189 assert_eq!(defs_map.as_ref(), data_contract.schema_defs())
190 }
191
192 #[test]
193 fn should_set_empty_schema_defs() {
194 let platform_version = PlatformVersion::latest();
195
196 let config = DataContractConfig::default_for_version(platform_version)
197 .expect("should create a default config");
198
199 let defs = platform_value!({
200 "test": {
201 "type": "string",
202 },
203 });
204
205 let defs_map = Some(defs.into_btree_string_map().expect("should convert to map"));
206
207 let schema = platform_value!({
208 "type": "object",
209 "properties": {
210 "a": {
211 "type": "string",
212 "maxLength": 10,
213 "position": 0
214 }
215 },
216 "additionalProperties": false,
217 });
218
219 let serialization_format = DataContractInSerializationFormatV0 {
220 id: Identifier::random(),
221 config,
222 version: 0,
223 owner_id: Default::default(),
224 schema_defs: defs_map,
225 document_schemas: BTreeMap::from([("document_type_name".to_string(), schema)]),
226 };
227
228 let mut data_contract = DataContractV1::try_from_platform_versioned(
229 serialization_format.into(),
230 true,
231 &mut vec![],
232 platform_version,
233 )
234 .expect("should create a contract from serialization format");
235
236 data_contract
237 .set_schema_defs(None, true, &mut vec![], platform_version)
238 .expect("should set defs");
239
240 assert_eq!(None, data_contract.schema_defs());
241 assert_eq!(
242 1,
243 data_contract.document_types().len(),
244 "document types should be preserved after clearing schema defs"
245 );
246 }
247}