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