Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow setting null values on doc fields #2273

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/ctype.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (t CType) IsSupportedFieldCType() bool {
func (t CType) IsCompatibleWith(kind FieldKind) bool {
switch t {
case PN_COUNTER:
if kind == FieldKind_INT || kind == FieldKind_FLOAT {
if kind == FieldKind_NILLABLE_INT || kind == FieldKind_NILLABLE_FLOAT {
return true
}
return false
Expand Down
60 changes: 30 additions & 30 deletions client/descriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,35 +155,35 @@
switch f {
case FieldKind_DocID:
return "ID"
case FieldKind_BOOL:
case FieldKind_NILLABLE_BOOL:
return "Boolean"
case FieldKind_NILLABLE_BOOL_ARRAY:
return "[Boolean]"
case FieldKind_BOOL_ARRAY:
return "[Boolean!]"
case FieldKind_INT:
case FieldKind_NILLABLE_INT:
return "Int"
case FieldKind_NILLABLE_INT_ARRAY:
return "[Int]"
case FieldKind_INT_ARRAY:
return "[Int!]"
case FieldKind_DATETIME:
case FieldKind_NILLABLE_DATETIME:

Check warning on line 170 in client/descriptions.go

View check run for this annotation

Codecov / codecov/patch

client/descriptions.go#L170

Added line #L170 was not covered by tests
return "DateTime"
case FieldKind_FLOAT:
case FieldKind_NILLABLE_FLOAT:

Check warning on line 172 in client/descriptions.go

View check run for this annotation

Codecov / codecov/patch

client/descriptions.go#L172

Added line #L172 was not covered by tests
return "Float"
case FieldKind_NILLABLE_FLOAT_ARRAY:
return "[Float]"
case FieldKind_FLOAT_ARRAY:
return "[Float!]"
case FieldKind_STRING:
case FieldKind_NILLABLE_STRING:
return "String"
case FieldKind_NILLABLE_STRING_ARRAY:
return "[String]"
case FieldKind_STRING_ARRAY:
return "[String!]"
case FieldKind_BLOB:
case FieldKind_NILLABLE_BLOB:

Check warning on line 184 in client/descriptions.go

View check run for this annotation

Codecov / codecov/patch

client/descriptions.go#L184

Added line #L184 was not covered by tests
return "Blob"
case FieldKind_JSON:
case FieldKind_NILLABLE_JSON:

Check warning on line 186 in client/descriptions.go

View check run for this annotation

Codecov / codecov/patch

client/descriptions.go#L186

Added line #L186 was not covered by tests
return "JSON"
default:
return fmt.Sprint(uint8(f))
Expand All @@ -192,22 +192,22 @@

// Note: These values are serialized and persisted in the database, avoid modifying existing values.
const (
FieldKind_None FieldKind = 0
FieldKind_DocID FieldKind = 1
FieldKind_BOOL FieldKind = 2
FieldKind_BOOL_ARRAY FieldKind = 3
FieldKind_INT FieldKind = 4
FieldKind_INT_ARRAY FieldKind = 5
FieldKind_FLOAT FieldKind = 6
FieldKind_FLOAT_ARRAY FieldKind = 7
_ FieldKind = 8 // safe to repurpose (was never used)
_ FieldKind = 9 // safe to repurpose (previously old field)
FieldKind_DATETIME FieldKind = 10
FieldKind_STRING FieldKind = 11
FieldKind_STRING_ARRAY FieldKind = 12
FieldKind_BLOB FieldKind = 13
FieldKind_JSON FieldKind = 14
_ FieldKind = 15 // safe to repurpose (was never used)
FieldKind_None FieldKind = 0
FieldKind_DocID FieldKind = 1
FieldKind_NILLABLE_BOOL FieldKind = 2
FieldKind_BOOL_ARRAY FieldKind = 3
FieldKind_NILLABLE_INT FieldKind = 4
FieldKind_INT_ARRAY FieldKind = 5
FieldKind_NILLABLE_FLOAT FieldKind = 6
FieldKind_FLOAT_ARRAY FieldKind = 7
_ FieldKind = 8 // safe to repurpose (was never used)
_ FieldKind = 9 // safe to repurpose (previously old field)
FieldKind_NILLABLE_DATETIME FieldKind = 10
FieldKind_NILLABLE_STRING FieldKind = 11
FieldKind_STRING_ARRAY FieldKind = 12
FieldKind_NILLABLE_BLOB FieldKind = 13
FieldKind_NILLABLE_JSON FieldKind = 14
_ FieldKind = 15 // safe to repurpose (was never used)

// Embedded object, but accessed via foreign keys
FieldKind_FOREIGN_OBJECT FieldKind = 16
Expand All @@ -230,21 +230,21 @@
// equality is not guaranteed.
var FieldKindStringToEnumMapping = map[string]FieldKind{
"ID": FieldKind_DocID,
"Boolean": FieldKind_BOOL,
"Boolean": FieldKind_NILLABLE_BOOL,
"[Boolean]": FieldKind_NILLABLE_BOOL_ARRAY,
"[Boolean!]": FieldKind_BOOL_ARRAY,
"Int": FieldKind_INT,
"Int": FieldKind_NILLABLE_INT,
"[Int]": FieldKind_NILLABLE_INT_ARRAY,
"[Int!]": FieldKind_INT_ARRAY,
"DateTime": FieldKind_DATETIME,
"Float": FieldKind_FLOAT,
"DateTime": FieldKind_NILLABLE_DATETIME,
"Float": FieldKind_NILLABLE_FLOAT,
"[Float]": FieldKind_NILLABLE_FLOAT_ARRAY,
"[Float!]": FieldKind_FLOAT_ARRAY,
"String": FieldKind_STRING,
"String": FieldKind_NILLABLE_STRING,
"[String]": FieldKind_NILLABLE_STRING_ARRAY,
"[String!]": FieldKind_STRING_ARRAY,
"Blob": FieldKind_BLOB,
"JSON": FieldKind_JSON,
"Blob": FieldKind_NILLABLE_BLOB,
"JSON": FieldKind_NILLABLE_JSON,
}

// RelationType describes the type of relation between two types.
Expand Down
30 changes: 25 additions & 5 deletions client/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,33 @@
return docs, nil
}

func isNillableKind(kind FieldKind) bool {
switch kind {
case FieldKind_NILLABLE_STRING, FieldKind_NILLABLE_BLOB, FieldKind_NILLABLE_JSON,
FieldKind_NILLABLE_BOOL, FieldKind_NILLABLE_FLOAT, FieldKind_NILLABLE_DATETIME,
FieldKind_NILLABLE_INT:
return true
default:
return false
}
}

// validateFieldSchema takes a given value as an interface,
// and ensures it matches the supplied field description.
// It will do any minor parsing, like dates, and return
// the typed value again as an interface.
func validateFieldSchema(val any, field FieldDescription) (any, error) {
if isNillableKind(field.Kind) {
if val == nil {
return nil, nil
}

Check warning on line 193 in client/document.go

View check run for this annotation

Codecov / codecov/patch

client/document.go#L192-L193

Added lines #L192 - L193 were not covered by tests
if v, ok := val.(*fastjson.Value); ok && v.Type() == fastjson.TypeNull {
return nil, nil
}
}

switch field.Kind {
case FieldKind_DocID, FieldKind_STRING, FieldKind_BLOB, FieldKind_JSON:
case FieldKind_DocID, FieldKind_NILLABLE_STRING, FieldKind_NILLABLE_BLOB, FieldKind_NILLABLE_JSON:
return getString(val)

case FieldKind_STRING_ARRAY:
Expand All @@ -186,7 +206,7 @@
case FieldKind_NILLABLE_STRING_ARRAY:
return getNillableArray(val, getString)

case FieldKind_BOOL:
case FieldKind_NILLABLE_BOOL:
return getBool(val)

case FieldKind_BOOL_ARRAY:
Expand All @@ -195,7 +215,7 @@
case FieldKind_NILLABLE_BOOL_ARRAY:
return getNillableArray(val, getBool)

case FieldKind_FLOAT:
case FieldKind_NILLABLE_FLOAT:
return getFloat64(val)

case FieldKind_FLOAT_ARRAY:
Expand All @@ -204,10 +224,10 @@
case FieldKind_NILLABLE_FLOAT_ARRAY:
return getNillableArray(val, getFloat64)

case FieldKind_DATETIME:
case FieldKind_NILLABLE_DATETIME:
return getDateTime(val)

case FieldKind_INT:
case FieldKind_NILLABLE_INT:
return getInt64(val)

case FieldKind_INT_ARRAY:
Expand Down
4 changes: 2 additions & 2 deletions client/document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ var (
{
Name: "Name",
Typ: LWW_REGISTER,
Kind: FieldKind_STRING,
Kind: FieldKind_NILLABLE_STRING,
},
{
Name: "Age",
Typ: LWW_REGISTER,
Kind: FieldKind_INT,
Kind: FieldKind_NILLABLE_INT,
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions core/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func DecodeFieldValue(fieldDesc client.FieldDescription, val any) (any, error) {
}
} else { // CBOR often encodes values typed as floats as ints
switch fieldDesc.Kind {
case client.FieldKind_FLOAT:
case client.FieldKind_NILLABLE_FLOAT:
switch v := val.(type) {
case int64:
return float64(v), nil
Expand All @@ -107,7 +107,7 @@ func DecodeFieldValue(fieldDesc client.FieldDescription, val any) (any, error) {
case uint:
return float64(v), nil
}
case client.FieldKind_INT:
case client.FieldKind_NILLABLE_INT:
switch v := val.(type) {
case float64:
return int64(v), nil
Expand All @@ -120,7 +120,7 @@ func DecodeFieldValue(fieldDesc client.FieldDescription, val any) (any, error) {
case uint:
return int64(v), nil
}
case client.FieldKind_DATETIME:
case client.FieldKind_NILLABLE_DATETIME:
switch v := val.(type) {
case string:
return time.Parse(time.RFC3339, v)
Expand Down
12 changes: 6 additions & 6 deletions db/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@

func getValidateIndexFieldFunc(kind client.FieldKind) func(any) bool {
switch kind {
case client.FieldKind_STRING, client.FieldKind_FOREIGN_OBJECT:
case client.FieldKind_NILLABLE_STRING, client.FieldKind_FOREIGN_OBJECT:
return canConvertIndexFieldValue[string]
case client.FieldKind_INT:
case client.FieldKind_NILLABLE_INT:
return canConvertIndexFieldValue[int64]
case client.FieldKind_FLOAT:
case client.FieldKind_NILLABLE_FLOAT:
return canConvertIndexFieldValue[float64]
case client.FieldKind_BOOL:
case client.FieldKind_NILLABLE_BOOL:

Check warning on line 53 in db/index.go

View check run for this annotation

Codecov / codecov/patch

db/index.go#L53

Added line #L53 was not covered by tests
return canConvertIndexFieldValue[bool]
case client.FieldKind_BLOB:
case client.FieldKind_NILLABLE_BLOB:

Check warning on line 55 in db/index.go

View check run for this annotation

Codecov / codecov/patch

db/index.go#L55

Added line #L55 was not covered by tests
return func(val any) bool {
blobStrVal, ok := val.(string)
if !ok {
return false
}
return types.BlobPattern.MatchString(blobStrVal)
}
case client.FieldKind_DATETIME:
case client.FieldKind_NILLABLE_DATETIME:

Check warning on line 63 in db/index.go

View check run for this annotation

Codecov / codecov/patch

db/index.go#L63

Added line #L63 was not covered by tests
return func(val any) bool {
timeStrVal, ok := val.(string)
if !ok {
Expand Down
4 changes: 2 additions & 2 deletions merkle/crdt/merklecrdt.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ func InstanceWithStore(
), nil
case client.PN_COUNTER:
switch kind {
case client.FieldKind_INT:
case client.FieldKind_NILLABLE_INT:
return NewMerklePNCounter[int64](
store,
schemaVersionKey,
key,
fieldName,
), nil
case client.FieldKind_FLOAT:
case client.FieldKind_NILLABLE_FLOAT:
return NewMerklePNCounter[float64](
store,
schemaVersionKey,
Expand Down
2 changes: 1 addition & 1 deletion net/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var sd = client.SchemaDescription{
Fields: []client.FieldDescription{
{
Name: "test",
Kind: client.FieldKind_STRING,
Kind: client.FieldKind_NILLABLE_STRING,
Typ: client.LWW_REGISTER,
},
},
Expand Down
4 changes: 2 additions & 2 deletions planner/sum.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (p *Planner) isValueFloat(
return false, client.NewErrFieldNotExist(source.Name)
}
return fieldDescription.Kind == client.FieldKind_FLOAT_ARRAY ||
fieldDescription.Kind == client.FieldKind_FLOAT ||
fieldDescription.Kind == client.FieldKind_NILLABLE_FLOAT ||
fieldDescription.Kind == client.FieldKind_NILLABLE_FLOAT_ARRAY, nil
}

Expand Down Expand Up @@ -136,7 +136,7 @@ func (p *Planner) isValueFloat(
}

return fieldDescription.Kind == client.FieldKind_FLOAT_ARRAY ||
fieldDescription.Kind == client.FieldKind_FLOAT ||
fieldDescription.Kind == client.FieldKind_NILLABLE_FLOAT ||
fieldDescription.Kind == client.FieldKind_NILLABLE_FLOAT_ARRAY, nil
}

Expand Down
14 changes: 7 additions & 7 deletions request/graphql/schema/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,19 +455,19 @@ func astTypeToKind(t ast.Type) (client.FieldKind, error) {
case typeID:
return client.FieldKind_DocID, nil
case typeBoolean:
return client.FieldKind_BOOL, nil
return client.FieldKind_NILLABLE_BOOL, nil
case typeInt:
return client.FieldKind_INT, nil
return client.FieldKind_NILLABLE_INT, nil
case typeFloat:
return client.FieldKind_FLOAT, nil
return client.FieldKind_NILLABLE_FLOAT, nil
case typeDateTime:
return client.FieldKind_DATETIME, nil
return client.FieldKind_NILLABLE_DATETIME, nil
case typeString:
return client.FieldKind_STRING, nil
return client.FieldKind_NILLABLE_STRING, nil
case typeBlob:
return client.FieldKind_BLOB, nil
return client.FieldKind_NILLABLE_BLOB, nil
case typeJSON:
return client.FieldKind_JSON, nil
return client.FieldKind_NILLABLE_JSON, nil
default:
return client.FieldKind_FOREIGN_OBJECT, nil
}
Expand Down
Loading
Loading