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  }