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