File size: 3,357 Bytes
b110593
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//                           _       _
// __      _____  __ ___   ___  __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
//  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
//   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
//  Copyright Β© 2016 - 2024 Weaviate B.V. All rights reserved.
//
//  CONTACT: [email protected]
//

package schema

import (
	"fmt"
	"regexp"
)

var (
	validateClassNameRegex          *regexp.Regexp
	validatePropertyNameRegex       *regexp.Regexp
	validateNestedPropertyNameRegex *regexp.Regexp
	reservedPropertyNames           []string
)

const (
	ClassNameRegexCore      = `[A-Z][_0-9A-Za-z]*`
	ShardNameRegexCore      = `[A-Za-z0-9\-\_]{1,64}`
	PropertyNameRegex       = `[_A-Za-z][_0-9A-Za-z]*`
	NestedPropertyNameRegex = `[_A-Za-z][_0-9A-Za-z]*`
)

func init() {
	validateClassNameRegex = regexp.MustCompile(`^` + ClassNameRegexCore + `$`)
	validatePropertyNameRegex = regexp.MustCompile(`^` + PropertyNameRegex + `$`)
	validateNestedPropertyNameRegex = regexp.MustCompile(`^` + NestedPropertyNameRegex + `$`)
	reservedPropertyNames = []string{"_additional", "_id", "id"}
}

// ValidateClassName validates that this string is a valid class name (format wise)
func ValidateClassName(name string) (ClassName, error) {
	if validateClassNameRegex.MatchString(name) {
		return ClassName(name), nil
	}
	return "", fmt.Errorf("'%s' is not a valid class name", name)
}

// ValidatePropertyName validates that this string is a valid property name
func ValidatePropertyName(name string) (PropertyName, error) {
	if !validatePropertyNameRegex.MatchString(name) {
		return "", fmt.Errorf("'%s' is not a valid property name. "+
			"Property names in Weaviate are restricted to valid GraphQL names, "+
			"which must be β€œ/%s/”.", name, PropertyNameRegex)
	}
	return PropertyName(name), nil
}

// ValidateNestedPropertyName validates that this string is a valid nested property name
func ValidateNestedPropertyName(name, prefix string) error {
	if !validateNestedPropertyNameRegex.MatchString(name) {
		return fmt.Errorf("'%s' is not a valid nested property name of '%s'. "+
			"NestedProperty names in Weaviate are restricted to valid GraphQL names, "+
			"which must be β€œ/%s/”.", name, prefix, NestedPropertyNameRegex)
	}
	return nil
}

// ValidateReservedPropertyName validates that a string is not a reserved property name
func ValidateReservedPropertyName(name string) error {
	for i := range reservedPropertyNames {
		if name == reservedPropertyNames[i] {
			return fmt.Errorf("'%s' is a reserved property name", name)
		}
	}
	return nil
}

// AssertValidClassName assert that this string is a valid class name or
// panics and should therefore most likely not be used
func AssertValidClassName(name string) ClassName {
	n, err := ValidateClassName(name)
	if err != nil {
		panic(fmt.Sprintf("Did not expect to be handled '%s', an invalid class name", name))
	}
	return n
}

// AssertValidPropertyName asserts that this string is a valid property name or
// panics and should therefore most likely never be used.
func AssertValidPropertyName(name string) PropertyName {
	n, err := ValidatePropertyName(name)
	if err != nil {
		panic(fmt.Sprintf("Did not expect to be handled '%s', an invalid property name", name))
	}
	return n
}