-
Notifications
You must be signed in to change notification settings - Fork 174
Dashrews/ROX-13082 UUID searcher and common updates to set allow use of postgres UUID PR 1 of 4 #3679
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
Dashrews/ROX-13082 UUID searcher and common updates to set allow use of postgres UUID PR 1 of 4 #3679
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| package pgsearch | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "regexp" | ||
| "strings" | ||
|
|
||
| "github.com/pkg/errors" | ||
| pkgSearch "github.com/stackrox/rox/pkg/search" | ||
| "github.com/stackrox/rox/pkg/utils" | ||
| "github.com/stackrox/rox/pkg/uuid" | ||
| ) | ||
|
|
||
| func newUUIDQuery(ctx *queryAndFieldContext) (*QueryEntry, error) { | ||
| whereClause, err := newUUIDQueryWhereClause(ctx.qualifiedColumnName, ctx.value, ctx.queryModifiers...) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return qeWithSelectFieldIfNeeded(ctx, &whereClause, nil), nil | ||
| } | ||
|
|
||
| func newUUIDQueryWhereClause(columnName string, value string, queryModifiers ...pkgSearch.QueryModifier) (WhereClause, error) { | ||
| if len(value) == 0 { | ||
| return WhereClause{}, errors.New("value in search query cannot be empty") | ||
| } | ||
|
|
||
| if value == pkgSearch.WildcardString { | ||
| return WhereClause{ | ||
| Query: fmt.Sprintf("%s is not null", columnName), | ||
| Values: []interface{}{}, | ||
| equivalentGoFunc: func(foundValue interface{}) bool { | ||
| foundVal := strings.ToLower(foundValue.(string)) | ||
| return foundVal != "" | ||
| }, | ||
| }, nil | ||
| } | ||
|
|
||
| if len(queryModifiers) == 0 { | ||
| uuidVal, err := uuid.FromString(value) | ||
| if err != nil { | ||
| return WhereClause{}, errors.Wrapf(err, "value %q in search query must be valid UUID", value) | ||
| } | ||
| return WhereClause{ | ||
| Query: fmt.Sprintf("%s = $$", columnName), | ||
| Values: []interface{}{uuidVal}, | ||
| equivalentGoFunc: func(foundValue interface{}) bool { | ||
| return strings.EqualFold(foundValue.(string), value) | ||
| }, | ||
| }, nil | ||
| } | ||
| if queryModifiers[0] == pkgSearch.AtLeastOne { | ||
| panic("I dont think this is used") | ||
| } | ||
| var negationString string | ||
| negated := queryModifiers[0] == pkgSearch.Negation | ||
| if negated { | ||
| negationString = "!" | ||
| if len(queryModifiers) == 1 { | ||
| uuidVal, err := uuid.FromString(value) | ||
| if err != nil { | ||
| return WhereClause{}, errors.Wrapf(err, "value %q in search query must be valid UUID", value) | ||
| } | ||
| return WhereClause{ | ||
| Query: fmt.Sprintf("%s != $$", columnName), | ||
| Values: []interface{}{uuidVal}, | ||
| equivalentGoFunc: func(foundValue interface{}) bool { | ||
| return strings.EqualFold(foundValue.(string), value) != negated | ||
| }, | ||
| }, nil | ||
| } | ||
| queryModifiers = queryModifiers[1:] | ||
| } | ||
|
|
||
| switch queryModifiers[0] { | ||
| case pkgSearch.Regex: | ||
| re, err := regexp.Compile(value) | ||
| if err != nil { | ||
| return WhereClause{}, fmt.Errorf("invalid regexp %s: %w", value, err) | ||
| } | ||
|
|
||
| if value != "*" { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be missing some context but why only
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @md2119 I didn't think that made a lot of sense for a UUID. What would be the use case for that since UUIDs are random? There is no logical grouping of say all UUIDs that start with
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a breaking change given that we currently support any regex on the string fields which are planned to be converted uuid. At the very least we should call it out in the docs.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return WhereClause{}, fmt.Errorf("invalid regexp %s for UUID field", value) | ||
| } | ||
| return WhereClause{ | ||
| Query: fmt.Sprintf("%s is not null", columnName), | ||
| Values: []interface{}{value}, | ||
| equivalentGoFunc: func(foundValue interface{}) bool { | ||
| foundVal := strings.ToLower(foundValue.(string)) | ||
| return re.MatchString(foundVal) != negated | ||
| }, | ||
| }, nil | ||
| case pkgSearch.Equality: | ||
| uuidVal, err := uuid.FromString(value) | ||
| if err != nil { | ||
| return WhereClause{}, errors.Wrapf(err, "value %q in search query must be valid UUID", value) | ||
| } | ||
| return WhereClause{ | ||
| Query: fmt.Sprintf("%s %s= $$", columnName, negationString), | ||
| Values: []interface{}{uuidVal}, | ||
| equivalentGoFunc: func(foundValue interface{}) bool { | ||
| return strings.EqualFold(foundValue.(string), value) != negated | ||
| }, | ||
| }, nil | ||
| } | ||
| err := fmt.Errorf("unknown query modifier: %s", queryModifiers[0]) | ||
| utils.Should(err) | ||
| return WhereClause{}, err | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:I might be wrong her, but I expect UUID columns to have an internal representation in postgres as unsigned int of size 128 bit. As a consequence I'd expect the ordering of values to be identical for the internal integer representation and the associated text representation (binary values 0000 to 1111 matching text representations from 0 to f - 0x30 to 0x39 and 0x61 to 0x66 - ).
I don't think the cast to text hurts that much, but if it's unnecessary, we might as well want to skip it for ordering.
I'd say it can stay as is for now. I don't have advanced enough knowledge on the topic to drive the eventual decision here.