github.com/weaviate/weaviate@v1.24.6/entities/schema/validation.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package schema
    13  
    14  import (
    15  	"fmt"
    16  	"regexp"
    17  )
    18  
    19  var (
    20  	validateClassNameRegex          *regexp.Regexp
    21  	validatePropertyNameRegex       *regexp.Regexp
    22  	validateNestedPropertyNameRegex *regexp.Regexp
    23  	reservedPropertyNames           []string
    24  )
    25  
    26  const (
    27  	// Restricted by max length allowed for dir name (255 chars)
    28  	// As dir containing class data is named after class, 255 chars are allowed
    29  	classNameMaxLength = 255
    30  	ClassNameRegexCore = `[A-Z][_0-9A-Za-z]{0,254}`
    31  	ShardNameRegexCore = `[A-Za-z0-9\-\_]{1,64}`
    32  	// Restricted by max length allowed for dir name (255 chars)
    33  	// Property name is used to build dir names of various purposes containing property
    34  	// related data. Among them might be (depending on the settings):
    35  	// - geo.{property_name}.hnsw.commitlog.d
    36  	// - property_{property_name}__meta_count
    37  	// - property_{property_name}_propertyLength
    38  	// Last one seems to add the most additional characters (24) to property name,
    39  	// therefore poperty max lentgh should not exceed 255 - 24 = 231 chars.
    40  	propertyNameMaxLength = 231
    41  	PropertyNameRegex     = `[_A-Za-z][_0-9A-Za-z]{0,230}`
    42  	// Nested properties names are not used to build directory names (yet),
    43  	// no max length restriction is imposed
    44  	NestedPropertyNameRegex = `[_A-Za-z][_0-9A-Za-z]*`
    45  	// Target vector names must be GraphQL compliant names no longer then 230 characters
    46  	TargetVectorNameMaxLength = 230
    47  	TargetVectorNameRegex     = `[_A-Za-z][_0-9A-Za-z]{0,229}`
    48  )
    49  
    50  func init() {
    51  	validateClassNameRegex = regexp.MustCompile(`^` + ClassNameRegexCore + `$`)
    52  	validatePropertyNameRegex = regexp.MustCompile(`^` + PropertyNameRegex + `$`)
    53  	validateNestedPropertyNameRegex = regexp.MustCompile(`^` + NestedPropertyNameRegex + `$`)
    54  	reservedPropertyNames = []string{"_additional", "_id", "id"}
    55  }
    56  
    57  // ValidateClassName validates that this string is a valid class name (format wise)
    58  func ValidateClassName(name string) (ClassName, error) {
    59  	if len(name) > classNameMaxLength {
    60  		return "", fmt.Errorf("'%s' is not a valid class name. Name should not be longer than %d characters.",
    61  			name, classNameMaxLength)
    62  	}
    63  	if !validateClassNameRegex.MatchString(name) {
    64  		return "", fmt.Errorf("'%s' is not a valid class name", name)
    65  	}
    66  	return ClassName(name), nil
    67  }
    68  
    69  // ValidatePropertyName validates that this string is a valid property name
    70  func ValidatePropertyName(name string) (PropertyName, error) {
    71  	if len(name) > propertyNameMaxLength {
    72  		return "", fmt.Errorf("'%s' is not a valid property name. Name should not be longer than %d characters.",
    73  			name, propertyNameMaxLength)
    74  	}
    75  	if !validatePropertyNameRegex.MatchString(name) {
    76  		return "", fmt.Errorf("'%s' is not a valid property name. "+
    77  			"Property names in Weaviate are restricted to valid GraphQL names, "+
    78  			"which must be “/%s/”.", name, PropertyNameRegex)
    79  	}
    80  	return PropertyName(name), nil
    81  }
    82  
    83  // ValidateNestedPropertyName validates that this string is a valid nested property name
    84  func ValidateNestedPropertyName(name, prefix string) error {
    85  	if !validateNestedPropertyNameRegex.MatchString(name) {
    86  		return fmt.Errorf("'%s' is not a valid nested property name of '%s'. "+
    87  			"NestedProperty names in Weaviate are restricted to valid GraphQL names, "+
    88  			"which must be “/%s/”.", name, prefix, NestedPropertyNameRegex)
    89  	}
    90  	return nil
    91  }
    92  
    93  // ValidateReservedPropertyName validates that a string is not a reserved property name
    94  func ValidateReservedPropertyName(name string) error {
    95  	for i := range reservedPropertyNames {
    96  		if name == reservedPropertyNames[i] {
    97  			return fmt.Errorf("'%s' is a reserved property name", name)
    98  		}
    99  	}
   100  	return nil
   101  }
   102  
   103  // AssertValidClassName assert that this string is a valid class name or
   104  // panics and should therefore most likely not be used
   105  func AssertValidClassName(name string) ClassName {
   106  	n, err := ValidateClassName(name)
   107  	if err != nil {
   108  		panic(fmt.Sprintf("Did not expect to be handled '%s', an invalid class name", name))
   109  	}
   110  	return n
   111  }
   112  
   113  // AssertValidPropertyName asserts that this string is a valid property name or
   114  // panics and should therefore most likely never be used.
   115  func AssertValidPropertyName(name string) PropertyName {
   116  	n, err := ValidatePropertyName(name)
   117  	if err != nil {
   118  		panic(fmt.Sprintf("Did not expect to be handled '%s', an invalid property name", name))
   119  	}
   120  	return n
   121  }