• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 
16 #ifndef SCHEMA_OBJECT_H
17 #define SCHEMA_OBJECT_H
18 
19 #include <set>
20 #include <map>
21 #ifndef OMIT_FLATBUFFER
22 #include <flatbuffers/idl.h>
23 #endif // OMIT_FLATBUFFER
24 #include "db_types.h"
25 #include "macro_utils.h"
26 #include "relational_schema_object.h"
27 #include "ischema.h"
28 #include "value_object.h"
29 
30 namespace DistributedDB {
31 using IndexName = FieldPath;
32 using IndexFieldInfo = std::pair<FieldPath, FieldType>;
33 using IndexInfo = std::vector<IndexFieldInfo>;
34 template<typename T> using PairConstPointer = std::pair<const T *, const T *>;
35 
36 struct IndexDifference {
37     std::map<IndexName, IndexInfo> change;
38     std::map<IndexName, IndexInfo> increase;
39     std::set<IndexName> decrease;
40 };
41 
42 class SchemaObject : public ISchema {
43 public:
44     static std::string GetExtractFuncName(SchemaType inSchemaType);
45     static std::string GenerateExtractSQL(SchemaType inSchemaType, const FieldPath &inFieldpath, FieldType inFieldType,
46         uint32_t skipSize, const std::string &accessStr = "");
47 
48     // Support default constructor, copy constructor and copy assignment
49     SchemaObject();
50     ~SchemaObject() = default;
51     SchemaObject(const SchemaObject &);
52     SchemaObject& operator=(const SchemaObject &);
53 #ifdef RELATIONAL_STORE
54     SchemaObject(const TableInfo &tableInfo);  // The construct func can only be used for query.
55 #endif  // RELATIONAL_STORE
56 
57     // Move constructor and move assignment is not need currently
58     SchemaObject(SchemaObject &&) = delete;
59     SchemaObject& operator=(SchemaObject &&) = delete;
60 
61     // Should be called on an invalid SchemaObject, create new SchemaObject if need to reparse
62     int ParseFromSchemaString(const std::string &inSchemaString) override;
63 
64     bool IsSchemaValid() const override;
65     SchemaType GetSchemaType() const override;
66 
67     // For Json-Schema : Unnecessary spacing will be removed and fieldname resorted by lexicographical order
68     // For FlatBuffer-Schema : Original binary schema(Base64 decoded if need)
69     std::string ToSchemaString() const override;
70 
71     uint32_t GetSkipSize() const;
72     std::map<IndexName, IndexInfo> GetIndexInfo() const;
73     bool IsIndexExist(const IndexName &indexName) const;
74 
75     // Return E_OK if queryale. outType will be set if path exist no matter binary or not
76     int CheckQueryableAndGetFieldType(const FieldPath &inPath, FieldType &outType) const;
77 
78     // Attention: it doesn't return E_OK. instead:
79     // E_JSON_PARSE_FAIL : the inSchemaString is not an valid json
80     // E_SCHEMA_PARSE_FAIL : the inSchemaString is not an valid schema
81     // E_SCHEMA_EQUAL_EXACTLY : the inSchema is exactly equal to this SchemaObject
82     // E_SCHEMA_UNEQUAL_COMPATIBLE : the inSchema is not equal to but only index differ with this SchemaObject
83     // E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE : the inSchema is not equal to but can upgrade from this SchemaObject
84     // E_SCHEMA_UNEQUAL_INCOMPATIBLE : the inSchema is not equal to and can not upgrade from this SchemaObject
85     int CompareAgainstSchemaString(const std::string &inSchemaString) const;
86     int CompareAgainstSchemaString(const std::string &inSchemaString, IndexDifference &indexDiffer) const;
87     int CompareAgainstSchemaObject(const SchemaObject &inSchemaObject) const;
88     int CompareAgainstSchemaObject(const SchemaObject &inSchemaObject, IndexDifference &indexDiffer) const;
89 
90     // Attention: it doesn't return E_OK. instead:
91     // E_VALUE_MATCH : Value match schema(no matter strict or compatible mode) without any change
92     // E_VALUE_MATCH_AMENDED : Value match schema(no matter strict or compatible mode) with some amendment
93     // E_VALUE_MISMATCH_FEILD_COUNT : Value contain more field then schema when in strict mode
94     // E_VALUE_MISMATCH_FEILD_TYPE : Type of some fields of value mismatch schema
95     // E_VALUE_MISMATCH_CONSTRAINT : Some fields of value violate the NotNull constraint against schema
96     // E_VALUE_MISMATCH_OTHER_REASON : Value mismatch schema because of other reason unmentioned
97     int CheckValueAndAmendIfNeed(ValueSource sourceType, ValueObject &inValue) const;
98 
99     // Currently only for flatBuffer-type schema and value.
100     // Accept the original entry-value, return E_OK or E_FLATBUFFER_VERIFY_FAIL.
101     int VerifyValue(ValueSource sourceType, const Value &inValue) const;
102     int VerifyValue(ValueSource sourceType, const RawValue &inValue) const;
103 
104     // Accept the original value from database. The cache will not be expanded. Return E_OK if nothing error.
105     // The ExtractValue is with nice performance by carefully not use std-class to avoid memory allocation.
106     // But currently it can only deal with path with $. prefix and only one depth. However, meet current demand.
107     int ExtractValue(ValueSource sourceType, RawString inPath, const RawValue &inValue, TypeValue &outExtract,
108         std::vector<uint8_t> *cache) const;
109 private:
110     enum class SchemaMode {
111         STRICT,
112         COMPATIBLE,
113     };
114     using SchemaDefine = std::map<FieldPath, SchemaAttribute>;
115 
116     // For Json-Schema : Parsing related methods.
117     int ParseJsonSchema(const JsonObject &inJsonObject);
118     int CheckMetaFieldCountAndType(const JsonObject &inJsonObject) const;
119     int ParseCheckSchemaVersionMode(const JsonObject &inJsonObject);
120     int ParseCheckSchemaDefine(const JsonObject &inJsonObject);
121     int CheckSchemaDefineItemDecideAttribute(const JsonObject &inJsonObject, const FieldPath &inPath, FieldType inType,
122         SchemaAttribute &outAttr) const;
123     int ParseCheckSchemaIndexes(const JsonObject &inJsonObject);
124     int ParseCheckSchemaSkipSize(const JsonObject &inJsonObject);
125 
126     // For both Json-Schema and FlatBuffer-Schema.
127     int ParseCheckEachIndexFromStringArray(const std::vector<std::string> &inStrArray);
128     int CheckFieldPathIndexableThenSave(const std::vector<FieldPath> &inPathVec, IndexInfo &infoToSave);
129 
130     // CompareAgainstSchemaObject related sub methods
131     int CompareSchemaVersionMode(const SchemaObject &newSchema) const;
132     int CompareSchemaSkipSize(const SchemaObject &newSchema) const;
133     int CompareSchemaDefine(const SchemaObject &newSchema) const;
134     int CompareSchemaDefineByDepth(const SchemaDefine &oldDefine, const SchemaDefine &newDefine) const;
135     int CompareSchemaAttribute(const SchemaAttribute &oldAttr, const SchemaAttribute &newAttr) const;
136     int CompareSchemaDefaultValue(const SchemaAttribute &oldAttr, const SchemaAttribute &newAttr) const;
137     int CompareSchemaIndexes(const SchemaObject &newSchema, IndexDifference &indexDiffer) const;
138 
139     // CheckValueAndAmendIfNeed related sub methods
140     int CheckValue(const ValueObject &inValue, std::set<FieldPath> &lackingPaths) const;
141     int AmendValueIfNeed(ValueObject &inValue, const std::set<FieldPath> &lackingPaths, bool &amended) const;
142 
143     // It is better using a class to represent flatBuffer-Schema related other than more private method(As well as for
144     // Json-Schema in the future refactor). Delegation is chosen other than inheritance for accessing SchemaObject.
145     // Choose inner-class other than friend-class to avoid forward declaration and using pointer.
146     class FlatBufferSchema {
147     public:
FlatBufferSchema(SchemaObject & owner)148         FlatBufferSchema(SchemaObject &owner) : owner_(owner) {};
149         ~FlatBufferSchema() = default;
150         DISABLE_COPY_ASSIGN_MOVE(FlatBufferSchema);
151         // Copy-Constructor can not define due to Const-Ref member. Code standard require copy assignment be deleted.
152         void CopyFrom(const FlatBufferSchema &other);
153 
154         std::string GetDescription() const;
155 
156         // Judge whether it's flatbuffer type schema, no matter whether it is Base64 encoded, provide a decoded one.
157         static bool IsFlatBufferSchema(const std::string &inOriginal, std::string &outDecoded);
158 
159         // Accept a decoded and verified flatbuffer-schema, then parse its content
160         int ParseFlatBufferSchema(const std::string &inDecoded);
161 
162         // Compare based on self.
163         // return E_SCHEMA_EQUAL_EXACTLY or E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE or E_SCHEMA_UNEQUAL_INCOMPATIBLE
164         int CompareFlatBufferDefine(const FlatBufferSchema &other) const;
165 
166         // Accept a no-skipsize(so byte-aligned) value, return E_OK or E_FLATBUFFER_VERIFY_FAIL.
167         int VerifyFlatBufferValue(const RawValue &inValue, bool tryNoSizePrefix) const;
168 
169         // Accept a no-skipsize(so byte-aligned) value.
170         int ExtractFlatBufferValue(RawString inPath, const RawValue &inValue, TypeValue &outExtract,
171             bool tryNoSizePrefix) const;
172     private:
173 #ifndef OMIT_FLATBUFFER
174         using RawIndexInfos = std::map<std::string, std::string>; // First the fieldName, second the index-attr value.
175 
176         const reflection::Schema *GetSchema() const;
177 
178         int ParseCheckRootTableAttribute(const reflection::Object &rootTable);
179         int ParseCheckRootTableDefine(const reflection::Schema &schema, const reflection::Object &rootTable,
180             RawIndexInfos &indexCollect);
181         int ParseCheckFieldInfo(const reflection::Schema &schema, const reflection::Field &field,
182             const FieldPath &path, RawIndexInfos &indexCollect);
183         void CollectRawIndexInfos(const reflection::Field &field, RawIndexInfos &indexCollect) const;
184         int ParseCheckStructDefine(const reflection::Schema &schema, const reflection::Field &field,
185             const FieldPath &path);
186         int ParseCheckIndexes(const RawIndexInfos &indexCollect);
187 
188         int CompareTableOrStructDefine(const PairConstPointer<reflection::Schema> &bothSchema,
189             const PairConstPointer<reflection::Object> &bothObject, bool isRoot, std::set<std::string> &compared) const;
190         int CompareStruct(const PairConstPointer<reflection::Schema> &bothSchema,
191             const PairConstPointer<reflection::Field> &bothField, std::set<std::string> &compared) const;
192 #endif
193         SchemaObject &owner_;
194         std::string description_;
195     };
196 
197     bool isValid_ = false;
198     SchemaType schemaType_ = SchemaType::NONE; // Default NONE
199     FlatBufferSchema flatbufferSchema_;
200     std::string schemaString_; // The minified and valid schemaString
201 
202     std::string schemaVersion_;
203     SchemaMode schemaMode_ = SchemaMode::STRICT; // Only for Json-Schema, Consider refactor into JsonSchema class
204     uint32_t schemaSkipSize_ = 0;
205     std::map<IndexName, IndexInfo> schemaIndexes_;
206     std::map<uint32_t, SchemaDefine> schemaDefine_; // SchemaDefine classified by the depth of fieldpath
207 };
208 } // namespace DistributedDB
209 
210 #endif // SCHEMA_OBJECT_H
211