From 419c39866f8b6f5c36629347ce59f08295a5a9a3 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Thu, 11 Dec 2025 10:57:45 +0100 Subject: [PATCH 1/2] Normalise key, owner, creator to be lower-case in queries --- query/language.go | 135 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 5 deletions(-) diff --git a/query/language.go b/query/language.go index 9815ac7..c56a77c 100644 --- a/query/language.go +++ b/query/language.go @@ -2,6 +2,7 @@ package query import ( "log/slog" + "strings" "github.com/alecthomas/participle/v2" "github.com/alecthomas/participle/v2/lexer" @@ -238,7 +239,6 @@ type EqualExpr struct { } func (e *EqualExpr) Normalise() *EqualExpr { - normalised := e if e.Paren != nil { p := e.Paren.Normalise() @@ -248,14 +248,41 @@ func (e *EqualExpr) Normalise() *EqualExpr { if len(p.Nested.Or.Right) == 0 && len(p.Nested.Or.Left.Right) == 0 { // This expression should already be properly normalised, we don't need to // call Normalise again here - normalised = &p.Nested.Or.Left.Left + return &p.Nested.Or.Left.Left } else { - normalised = &EqualExpr{Paren: p} + return &EqualExpr{Paren: p} } } - // Everything other than parenthesised expressions do not require further normalisation - return normalised + if e.LessThan != nil { + return &EqualExpr{LessThan: e.LessThan.Normalise()} + } + + if e.LessOrEqualThan != nil { + return &EqualExpr{LessOrEqualThan: e.LessOrEqualThan.Normalise()} + } + + if e.GreaterThan != nil { + return &EqualExpr{GreaterThan: e.GreaterThan.Normalise()} + } + + if e.GreaterOrEqualThan != nil { + return &EqualExpr{GreaterOrEqualThan: e.GreaterOrEqualThan.Normalise()} + } + + if e.Glob != nil { + return &EqualExpr{Glob: e.Glob.Normalise()} + } + + if e.Assign != nil { + return &EqualExpr{Assign: e.Assign.Normalise()} + } + + if e.Inclusion != nil { + return &EqualExpr{Inclusion: e.Inclusion.Normalise()} + } + + panic("This should not happen!") } func (e *EqualExpr) invert() *EqualExpr { @@ -325,6 +352,11 @@ type Glob struct { Value string `parser:"@String"` } +func (e *Glob) Normalise() *Glob { + // TODO do we need to change casing here too? + return e +} + func (e *Glob) invert() *Glob { return &Glob{ Var: e.Var, @@ -338,6 +370,21 @@ type LessThan struct { Value Value `parser:"@@"` } +func (e *LessThan) Normalise() *LessThan { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + val := strings.ToLower(*e.Value.String) + return &LessThan{ + Var: e.Var, + Value: Value{ + String: &val, + }, + } + default: + return e + } +} + func (e *LessThan) invert() *GreaterOrEqualThan { return &GreaterOrEqualThan{ Var: e.Var, @@ -350,6 +397,21 @@ type LessOrEqualThan struct { Value Value `parser:"@@"` } +func (e *LessOrEqualThan) Normalise() *LessOrEqualThan { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + val := strings.ToLower(*e.Value.String) + return &LessOrEqualThan{ + Var: e.Var, + Value: Value{ + String: &val, + }, + } + default: + return e + } +} + func (e *LessOrEqualThan) invert() *GreaterThan { return &GreaterThan{ Var: e.Var, @@ -362,6 +424,21 @@ type GreaterThan struct { Value Value `parser:"@@"` } +func (e *GreaterThan) Normalise() *GreaterThan { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + val := strings.ToLower(*e.Value.String) + return &GreaterThan{ + Var: e.Var, + Value: Value{ + String: &val, + }, + } + default: + return e + } +} + func (e *GreaterThan) invert() *LessOrEqualThan { return &LessOrEqualThan{ Var: e.Var, @@ -374,6 +451,21 @@ type GreaterOrEqualThan struct { Value Value `parser:"@@"` } +func (e *GreaterOrEqualThan) Normalise() *GreaterOrEqualThan { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + val := strings.ToLower(*e.Value.String) + return &GreaterOrEqualThan{ + Var: e.Var, + Value: Value{ + String: &val, + }, + } + default: + return e + } +} + func (e *GreaterOrEqualThan) invert() *LessThan { return &LessThan{ Var: e.Var, @@ -388,6 +480,21 @@ type Equality struct { Value Value `parser:"@@"` } +func (e *Equality) Normalise() *Equality { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + val := strings.ToLower(*e.Value.String) + return &Equality{ + Var: e.Var, + Value: Value{ + String: &val, + }, + } + default: + return e + } +} + func (e *Equality) invert() *Equality { return &Equality{ Var: e.Var, @@ -402,6 +509,24 @@ type Inclusion struct { Values Values `parser:"@@"` } +func (e *Inclusion) Normalise() *Inclusion { + switch e.Var { + case KeyAttributeKey, OwnerAttributeKey, CreatorAttributeKey: + vals := make([]string, 0, len(e.Values.Strings)) + for _, val := range e.Values.Strings { + vals = append(vals, strings.ToLower(val)) + } + return &Inclusion{ + Var: e.Var, + Values: Values{ + Strings: vals, + }, + } + default: + return e + } +} + func (e *Inclusion) invert() *Inclusion { return &Inclusion{ Var: e.Var, From 8c4824f1b1af24537b2692a8e2b42879a2d8fefb Mon Sep 17 00:00:00 2001 From: r-vdp Date: Thu, 11 Dec 2025 10:58:04 +0100 Subject: [PATCH 2/2] Restore the previous defaults for IncludeData in case no IncludeData was provided --- query/types.go | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/query/types.go b/query/types.go index cb043ab..b872e66 100644 --- a/query/types.go +++ b/query/types.go @@ -99,21 +99,25 @@ type Options struct { } func (options *Options) ToInternalQueryOptions() (*InternalQueryOptions, error) { + defaultIncludeData := &IncludeData{ + Key: true, + Expiration: true, + Owner: true, + Payload: true, + ContentType: true, + Attributes: true, + } switch { case options == nil: return &InternalQueryOptions{ - IncludeData: &IncludeData{ - Key: true, - }, + IncludeData: defaultIncludeData, }, nil case options.IncludeData == nil: return &InternalQueryOptions{ - IncludeData: &IncludeData{ - Key: true, - }, - OrderBy: options.OrderBy, - AtBlock: options.AtBlock, - Cursor: options.Cursor, + IncludeData: defaultIncludeData, + OrderBy: options.OrderBy, + AtBlock: options.AtBlock, + Cursor: options.Cursor, }, nil default: iq := InternalQueryOptions{