Skip to content

Commit

Permalink
Get the unit tests to pass.
Browse files Browse the repository at this point in the history
  • Loading branch information
ericpromislow committed Nov 14, 2024
1 parent a90d64c commit 2a2272b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 28 deletions.
51 changes: 28 additions & 23 deletions pkg/cache/sql/informer/listoption_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ var (
)

const (
matchFmt = `%%%s%%`
strictMatchFmt = `%s`
createFieldsTableFmt = `CREATE TABLE "%s_fields" (
matchFmt = `%%%s%%`
strictMatchFmt = `%s`
escapeBackslashDirective = ` ESCAPE '\'` // The leading space is crucial for unit tests only
createFieldsTableFmt = `CREATE TABLE "%s_fields" (
key TEXT NOT NULL PRIMARY KEY,
%s
)`
Expand Down Expand Up @@ -424,8 +425,8 @@ func (l *ListOptionIndexer) ListByOptions(ctx context.Context, lo ListOptions, p
// assemble and log the final query
query += limitClause
query += offsetClause
logrus.Infof("ListOptionIndexer prepared statement: %v", query)
logrus.Infof("Params: %v", params)
logrus.Debugf("ListOptionIndexer prepared statement: %v", query)
logrus.Debugf("Params: %v", params)

// execute
stmt := l.Prepare(query)
Expand Down Expand Up @@ -534,6 +535,7 @@ func (l *ListOptionIndexer) buildORClauseFromFilters(orFilters OrFilter) (string

func (l *ListOptionIndexer) getFieldFilter(filter Filter) (string, []any, error) {
opString := ""
escapeString := ""
columnName := toColumnName(filter.Field)
if err := l.validateColumn(columnName); err != nil {
return "", nil, err
Expand All @@ -542,21 +544,23 @@ func (l *ListOptionIndexer) getFieldFilter(filter Filter) (string, []any, error)
case Eq:
if filter.Partial {
opString = "LIKE"
escapeString = escapeBackslashDirective
} else {
opString = "="
}
clause := fmt.Sprintf((`f."%s" %s ?`), columnName, opString)
clause := fmt.Sprintf(`f."%s" %s ?%s`, columnName, opString, escapeString)
return clause, []any{formatMatchTarget(filter)}, nil
case NotEq:
if filter.Partial {
opString = "NOT LIKE"
escapeString = escapeBackslashDirective
} else {
opString = "!="
}
clause := fmt.Sprintf(`(f."%s" %s ?)`, columnName, opString)
clause := fmt.Sprintf(`f."%s" %s ?%s`, columnName, opString, escapeString)
return clause, []any{formatMatchTarget(filter)}, nil
case Exists:
clause := fmt.Sprintf(`(f."%s" IS NOT NULL)`, columnName)
clause := fmt.Sprintf(`f."%s" IS NOT NULL`, columnName)
return clause, []any{}, nil
case In:
fallthrough
Expand All @@ -569,7 +573,7 @@ func (l *ListOptionIndexer) getFieldFilter(filter Filter) (string, []any, error)
if filter.Op == "notin" {
opString = "NOT IN"
}
clause := fmt.Sprintf(`(f."%s" %s IN %s)`, columnName, opString, target)
clause := fmt.Sprintf(`f."%s" %s IN %s`, columnName, opString, target)
matches := make([]any, len(filter.Matches))
for i, match := range filter.Matches {
matches[i] = match
Expand All @@ -582,38 +586,38 @@ func (l *ListOptionIndexer) getFieldFilter(filter Filter) (string, []any, error)

func (l *ListOptionIndexer) getLabelFilter(filter Filter) (string, []any, error) {
opString := ""
columnName := toColumnName(filter.Field)
if err := l.validateColumn(columnName); err != nil {
return "", nil, err
}
escapeString := ""
if len(filter.Field) < 3 || filter.Field[0] != "metadata" || filter.Field[1] != "labels" {
return "", nil, fmt.Errorf("expecting a metadata.labels field, got '%s'", toColumnName(filter.Field))
return "", nil, fmt.Errorf("expecting a metadata.labels field, got '%s'", strings.Join(filter.Field, "."))
}
matchFmtToUse := strictMatchFmt
labelName := filter.Field[2]
switch filter.Op {
case Eq:
if filter.Partial {
opString = "LIKE"
escapeString = escapeBackslashDirective
matchFmtToUse = matchFmt
} else {
opString = "="
}
clause := fmt.Sprintf(`(lt.label = ? AND lt.value %s ?)`, opString)
return clause, []any{formatMatchTargetWithFormatter(filter.Field[2], matchFmtToUse), formatMatchTargetWithFormatter(filter.Matches[0], matchFmtToUse)}, nil
clause := fmt.Sprintf(`lt.label = ? AND lt.value %s ?%s`, opString, escapeString)
return clause, []any{labelName, formatMatchTargetWithFormatter(filter.Matches[0], matchFmtToUse)}, nil

case NotEq:
if filter.Partial {
opString = "NOT LIKE"
escapeString = escapeBackslashDirective
matchFmtToUse = matchFmt
} else {
opString = "!="
}
clause := fmt.Sprintf(`(lt.label = ? AND lt.value %s ?)`, opString)
return clause, []any{formatMatchTargetWithFormatter(filter.Field[2], matchFmtToUse), formatMatchTargetWithFormatter(filter.Matches[0], matchFmtToUse)}, nil
clause := fmt.Sprintf(`lt.label = ? AND lt.value %s ?%s`, opString, escapeString)
return clause, []any{labelName, formatMatchTargetWithFormatter(filter.Matches[0], matchFmtToUse)}, nil

case Exists:
clause := fmt.Sprintf(`(lt.label = ?)`)
return clause, []any{formatMatchTargetWithFormatter(filter.Field[2], strictMatchFmt)}, nil
clause := fmt.Sprintf(`lt.label = ?`)
return clause, []any{labelName}, nil

case In:
fallthrough
Expand All @@ -623,10 +627,11 @@ func (l *ListOptionIndexer) getLabelFilter(filter Filter) (string, []any, error)
if filter.Op == NotIn {
opString = "NOT IN"
}
clause := fmt.Sprintf(`(lt.label = ? AND lt.value %s %s)`, opString, target)
matches := make([]any, len(filter.Matches))
clause := fmt.Sprintf(`lt.label = ? AND lt.value %s %s`, opString, target)
matches := make([]any, len(filter.Matches)+1)
matches[0] = labelName
for i, match := range filter.Matches {
matches[i] = match
matches[i+1] = match
}
return clause, matches, nil
}
Expand Down
16 changes: 11 additions & 5 deletions pkg/cache/sql/informer/listoption_indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func TestListByOptions(t *testing.T) {
testObject := testStoreObject{Id: "something", Val: "a"}
unstrTestObjectMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&testObject)
assert.Nil(t, err)
// unstrTestObject

var tests []testCase
tests = append(tests, testCase{
description: "ListByOptions() with no errors returned, should not return an error",
Expand Down Expand Up @@ -305,6 +305,7 @@ func TestListByOptions(t *testing.T) {
Field: []string{"metadata", "somefield"},
Matches: []string{"somevalue"},
Op: Eq,
Partial: true,
},
},
},
Expand All @@ -318,7 +319,7 @@ func TestListByOptions(t *testing.T) {
(f."metadata.somefield" LIKE ? ESCAPE '\') AND
(FALSE)
ORDER BY f."metadata.name" ASC `,
expectedStmtArgs: []any{"somevalue"},
expectedStmtArgs: []any{"%somevalue%"},
returnList: []any{&unstructured.Unstructured{Object: unstrTestObjectMap}, &unstructured.Unstructured{Object: unstrTestObjectMap}},
expectedList: &unstructured.UnstructuredList{Object: map[string]interface{}{"items": []map[string]interface{}{unstrTestObjectMap, unstrTestObjectMap}}, Items: []unstructured.Unstructured{{Object: unstrTestObjectMap}, {Object: unstrTestObjectMap}}},
expectedContToken: "",
Expand All @@ -333,6 +334,7 @@ func TestListByOptions(t *testing.T) {
Field: []string{"metadata", "somefield"},
Matches: []string{"somevalue"},
Op: NotEq,
Partial: true,
},
},
},
Expand All @@ -346,7 +348,7 @@ func TestListByOptions(t *testing.T) {
(f."metadata.somefield" NOT LIKE ? ESCAPE '\') AND
(FALSE)
ORDER BY f."metadata.name" ASC `,
expectedStmtArgs: []any{"somevalue"},
expectedStmtArgs: []any{"%somevalue%"},
returnList: []any{&unstructured.Unstructured{Object: unstrTestObjectMap}, &unstructured.Unstructured{Object: unstrTestObjectMap}},
expectedList: &unstructured.UnstructuredList{Object: map[string]interface{}{"items": []map[string]interface{}{unstrTestObjectMap, unstrTestObjectMap}}, Items: []unstructured.Unstructured{{Object: unstrTestObjectMap}, {Object: unstrTestObjectMap}}},
expectedContToken: "",
Expand Down Expand Up @@ -396,11 +398,13 @@ func TestListByOptions(t *testing.T) {
Field: []string{"metadata", "somefield"},
Matches: []string{"someothervalue"},
Op: Eq,
Partial: true,
},
{
Field: []string{"metadata", "somefield"},
Matches: []string{"somethirdvalue"},
Op: NotEq,
Partial: true,
},
},
},
Expand All @@ -414,7 +418,7 @@ func TestListByOptions(t *testing.T) {
(f."metadata.somefield" LIKE ? ESCAPE '\' OR f."metadata.somefield" LIKE ? ESCAPE '\' OR f."metadata.somefield" NOT LIKE ? ESCAPE '\') AND
(FALSE)
ORDER BY f."metadata.name" ASC `,
expectedStmtArgs: []any{"%somevalue%", "someothervalue", "somethirdvalue"},
expectedStmtArgs: []any{"%somevalue%", "%someothervalue%", "%somethirdvalue%"},
returnList: []any{&unstructured.Unstructured{Object: unstrTestObjectMap}, &unstructured.Unstructured{Object: unstrTestObjectMap}},
expectedList: &unstructured.UnstructuredList{Object: map[string]interface{}{"items": []map[string]interface{}{unstrTestObjectMap, unstrTestObjectMap}}, Items: []unstructured.Unstructured{{Object: unstrTestObjectMap}, {Object: unstrTestObjectMap}}},
expectedContToken: "",
Expand All @@ -435,6 +439,7 @@ func TestListByOptions(t *testing.T) {
Field: []string{"status", "someotherfield"},
Matches: []string{"someothervalue"},
Op: NotEq,
Partial: true,
},
},
},
Expand All @@ -444,6 +449,7 @@ func TestListByOptions(t *testing.T) {
Field: []string{"metadata", "somefield"},
Matches: []string{"somethirdvalue"},
Op: Eq,
Partial: true,
},
},
},
Expand All @@ -459,7 +465,7 @@ func TestListByOptions(t *testing.T) {
(f."metadata.namespace" = ?) AND
(FALSE)
ORDER BY f."metadata.name" ASC `,
expectedStmtArgs: []any{"%somevalue%", "someothervalue", "somethirdvalue", "test4"},
expectedStmtArgs: []any{"%somevalue%", "%someothervalue%", "%somethirdvalue%", "test4"},
returnList: []any{&unstructured.Unstructured{Object: unstrTestObjectMap}, &unstructured.Unstructured{Object: unstrTestObjectMap}},
expectedList: &unstructured.UnstructuredList{Object: map[string]interface{}{"items": []map[string]interface{}{unstrTestObjectMap, unstrTestObjectMap}}, Items: []unstructured.Unstructured{{Object: unstrTestObjectMap}, {Object: unstrTestObjectMap}}},
expectedContToken: "",
Expand Down

0 comments on commit 2a2272b

Please sign in to comment.