github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/meta/property.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 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 package meta 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "strconv" 21 "strings" 22 23 "github.com/pingcap/errors" 24 "github.com/vescale/zgraph/parser/model" 25 ) 26 27 func (*Meta) propertyKey(propertyID uint16) []byte { 28 return PropertyKey(propertyID) 29 } 30 31 // PropertyKey encodes the propertyID into property key. 32 func PropertyKey(propertyID uint16) []byte { 33 return []byte(fmt.Sprintf("%s:%d", mPropertyPrefix, propertyID)) 34 } 35 36 // IsPropertyKey checks whether the property key comes from PropertyKey(). 37 func IsPropertyKey(propertyKey []byte) bool { 38 return strings.HasPrefix(string(propertyKey), mPropertyPrefix+":") 39 } 40 41 // ParsePropertyKey decodes the property key to get property id. 42 func ParsePropertyKey(propertyKey []byte) (int64, error) { 43 if !strings.HasPrefix(string(propertyKey), mPropertyPrefix) { 44 return 0, ErrInvalidString 45 } 46 47 propertyID := strings.TrimPrefix(string(propertyKey), mPropertyPrefix+":") 48 id, err := strconv.Atoi(propertyID) 49 return int64(id), errors.Trace(err) 50 } 51 52 func (m *Meta) checkPropertyExists(graphKey []byte, propertyKey []byte) error { 53 v, err := m.txn.HGet(graphKey, propertyKey) 54 if err == nil && v == nil { 55 err = ErrPropertyNotExists 56 } 57 return errors.Trace(err) 58 } 59 60 func (m *Meta) checkPropertyNotExists(graphKey []byte, propertyKey []byte) error { 61 v, err := m.txn.HGet(graphKey, propertyKey) 62 if err == nil && v != nil { 63 err = ErrPropertyExists 64 } 65 return errors.Trace(err) 66 } 67 68 // CreateProperty creates a property. 69 func (m *Meta) CreateProperty(graphID int64, propertyInfo *model.PropertyInfo) error { 70 // Check if graph exists. 71 graphKey := m.graphKey(graphID) 72 if err := m.checkGraphExists(graphKey); err != nil { 73 return errors.Trace(err) 74 } 75 76 // Check if property exists. 77 lableKey := m.propertyKey(propertyInfo.ID) 78 if err := m.checkPropertyNotExists(graphKey, lableKey); err != nil { 79 return errors.Trace(err) 80 } 81 82 data, err := json.Marshal(propertyInfo) 83 if err != nil { 84 return errors.Trace(err) 85 } 86 87 return m.txn.HSet(graphKey, lableKey, data) 88 } 89 90 // UpdateProperty updates the property. 91 func (m *Meta) UpdateProperty(graphID int64, propertyInfo *model.PropertyInfo) error { 92 // Check if graph exists. 93 graphKey := m.graphKey(graphID) 94 if err := m.checkGraphExists(graphKey); err != nil { 95 return errors.Trace(err) 96 } 97 98 // Check if property exists. 99 propertyKey := m.propertyKey(propertyInfo.ID) 100 if err := m.checkPropertyExists(graphKey, propertyKey); err != nil { 101 return errors.Trace(err) 102 } 103 104 data, err := json.Marshal(propertyInfo) 105 if err != nil { 106 return errors.Trace(err) 107 } 108 109 err = m.txn.HSet(graphKey, propertyKey, data) 110 return errors.Trace(err) 111 } 112 113 // DropProperty drops property in graph. 114 func (m *Meta) DropProperty(graphID int64, propertyID uint16) error { 115 // Check if graph exists. 116 graphKey := m.graphKey(graphID) 117 if err := m.checkGraphExists(graphKey); err != nil { 118 return errors.Trace(err) 119 } 120 121 // Check if property exists. 122 propertyKey := m.propertyKey(propertyID) 123 if err := m.checkPropertyExists(graphKey, propertyKey); err != nil { 124 return errors.Trace(err) 125 } 126 127 if err := m.txn.HDel(graphKey, propertyKey); err != nil { 128 return errors.Trace(err) 129 } 130 return nil 131 } 132 133 // ListProperties shows all properties in a graph. 134 func (m *Meta) ListProperties(graphID int64) ([]*model.PropertyInfo, error) { 135 graphKey := m.graphKey(graphID) 136 if err := m.checkGraphExists(graphKey); err != nil { 137 return nil, errors.Trace(err) 138 } 139 140 res, err := m.txn.HGetAll(graphKey) 141 if err != nil { 142 return nil, errors.Trace(err) 143 } 144 145 propertys := make([]*model.PropertyInfo, 0, len(res)/2) 146 for _, r := range res { 147 // only handle property meta 148 propertyKey := string(r.Field) 149 if !strings.HasPrefix(propertyKey, mPropertyPrefix) { 150 continue 151 } 152 153 tbInfo := &model.PropertyInfo{} 154 err = json.Unmarshal(r.Value, tbInfo) 155 if err != nil { 156 return nil, errors.Trace(err) 157 } 158 159 propertys = append(propertys, tbInfo) 160 } 161 162 return propertys, nil 163 } 164 165 // GetProperty gets the property value in a graph. 166 func (m *Meta) GetProperty(graphID int64, propertyID uint16) (*model.PropertyInfo, error) { 167 // Check if graph exists. 168 graphKey := m.graphKey(graphID) 169 if err := m.checkGraphExists(graphKey); err != nil { 170 return nil, errors.Trace(err) 171 } 172 173 propertyKey := m.propertyKey(propertyID) 174 value, err := m.txn.HGet(graphKey, propertyKey) 175 if err != nil || value == nil { 176 return nil, errors.Trace(err) 177 } 178 179 propertyInfo := &model.PropertyInfo{} 180 err = json.Unmarshal(value, propertyInfo) 181 return propertyInfo, errors.Trace(err) 182 }