fix(user): add search query for login name (#4173)

* fix(user): add search query for login name

* fix(user): change login name query to IN from EXISTS

* fix(loginname): include InQuery into ListQuery with SubSelect as possible datasource

* fix(user): apply suggestions from code review

Co-authored-by: Livio Spring <livio.a@gmail.com>

* fix: correct unit test for search query

Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com>
Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz
2022-10-31 13:03:23 +00:00
committed by GitHub
parent 92eeb68be9
commit 5d17da542d
10 changed files with 801 additions and 22 deletions

View File

@@ -13,13 +13,29 @@ import (
var (
testTable = table{
name: "test_table",
alias: "test_table",
instanceIDCol: "instance_id",
}
testTableAlias = table{
name: "test_table",
alias: "test_alias",
instanceIDCol: "instance_id",
}
testTable2 = table{
name: "test_table2",
alias: "test_table2",
}
testCol = Column{
name: "test_col",
table: testTable,
}
testColAlias = Column{
name: "test_col",
table: testTableAlias,
}
testCol2 = Column{
name: "test_col2",
table: testTable2,
}
testLowerCol = Column{
name: "test_lower_col",
table: testTable,
@@ -140,6 +156,620 @@ func TestSearchRequest_ToQuery(t *testing.T) {
}
}
func TestNewSubSelect(t *testing.T) {
type args struct {
column Column
queries []SearchQuery
}
tests := []struct {
name string
args args
want *SubSelect
wantErr func(error) bool
}{
{
name: "no query nil",
args: args{
column: testCol,
queries: nil,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrNothingSelected)
},
},
{
name: "no query zero",
args: args{
column: testCol,
queries: []SearchQuery{},
},
wantErr: func(err error) bool {
return errors.Is(err, ErrNothingSelected)
},
},
{
name: "no column 1",
args: args{
column: Column{},
queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}},
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "no column name 1",
args: args{
column: testNoCol,
queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}},
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "correct 1",
args: args{
column: testCol,
queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}},
},
want: &SubSelect{
Column: testCol,
Queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}},
},
},
{
name: "correct 3",
args: args{
column: testCol,
queries: []SearchQuery{&TextQuery{testCol, "horst1", TextEquals}, &TextQuery{testCol, "horst2", TextEquals}, &TextQuery{testCol, "horst3", TextEquals}},
},
want: &SubSelect{
Column: testCol,
Queries: []SearchQuery{&TextQuery{testCol, "horst1", TextEquals}, &TextQuery{testCol, "horst2", TextEquals}, &TextQuery{testCol, "horst3", TextEquals}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewSubSelect(tt.args.column, tt.args.queries)
if err != nil && tt.wantErr == nil {
t.Errorf("NewTextQuery() no error expected got %v", err)
return
} else if tt.wantErr != nil && !tt.wantErr(err) {
t.Errorf("NewTextQuery() unexpeted error = %v", err)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewTextQuery() = %v, want %v", got, tt.want)
}
})
}
}
func TestSubSelect_comp(t *testing.T) {
type fields struct {
Column Column
Queries []SearchQuery
}
type want struct {
query interface{}
isNil bool
}
tests := []struct {
name string
fields fields
want want
}{
{
name: "no queries",
fields: fields{
Column: testCol,
Queries: []SearchQuery{},
},
want: want{
query: sq.Select("test_table.test_col").From("test_table"),
},
},
{
name: "queries 1",
fields: fields{
Column: testCol,
Queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}},
},
want: want{
query: sq.Select("test_table.test_col").From("test_table").Where(sq.Eq{"test_table.test_col": interface{}("horst")}),
},
},
{
name: "queries 1 with alias",
fields: fields{
Column: testColAlias,
Queries: []SearchQuery{&TextQuery{testColAlias, "horst", TextEquals}},
},
want: want{
query: sq.Select("test_alias.test_col").From("test_table AS test_alias").Where(sq.Eq{"test_alias.test_col": interface{}("horst")}),
},
},
{
name: "queries 3",
fields: fields{
Column: testCol,
Queries: []SearchQuery{&TextQuery{testCol, "horst1", TextEquals}, &TextQuery{testCol, "horst2", TextEquals}, &TextQuery{testCol, "horst3", TextEquals}},
},
want: want{
query: sq.Select("test_table.test_col").From("test_table").From("test_table").Where(sq.Eq{"test_table.test_col": "horst1"}).From("test_table").Where(sq.Eq{"test_table.test_col": "horst2"}).From("test_table").Where(sq.Eq{"test_table.test_col": "horst3"}),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &SubSelect{
Column: tt.fields.Column,
Queries: tt.fields.Queries,
}
query := s.comp()
if query == nil && tt.want.isNil {
return
} else if tt.want.isNil && query != nil {
t.Error("query should not be nil")
}
if !reflect.DeepEqual(query, tt.want.query) {
t.Errorf("wrong query: want: %v, (%T), got: %v, (%T)", tt.want.query, tt.want.query, query, query)
}
})
}
}
func TestNewColumnComparisonQuery(t *testing.T) {
type args struct {
column Column
columnCompare Column
compare ColumnComparison
}
tests := []struct {
name string
args args
want *ColumnComparisonQuery
wantErr func(error) bool
}{
{
name: "too low compare",
args: args{
column: testCol,
columnCompare: testCol2,
compare: -1,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrInvalidCompare)
},
},
{
name: "too high compare",
args: args{
column: testCol,
columnCompare: testCol2,
compare: columnCompareMax,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrInvalidCompare)
},
},
{
name: "no column 1",
args: args{
column: Column{},
columnCompare: testCol2,
compare: ColumnEquals,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "no column 2",
args: args{
column: testCol,
columnCompare: Column{},
compare: ColumnEquals,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "no column name 1",
args: args{
column: testNoCol,
columnCompare: testCol2,
compare: ColumnEquals,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "no column name 2",
args: args{
column: testCol,
columnCompare: testNoCol,
compare: ColumnEquals,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "correct",
args: args{
column: testCol,
columnCompare: testCol2,
compare: ColumnEquals,
},
want: &ColumnComparisonQuery{
Column1: testCol,
Column2: testCol2,
Compare: ColumnEquals,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewColumnComparisonQuery(tt.args.column, tt.args.columnCompare, tt.args.compare)
if err != nil && tt.wantErr == nil {
t.Errorf("NewTextQuery() no error expected got %v", err)
return
} else if tt.wantErr != nil && !tt.wantErr(err) {
t.Errorf("NewTextQuery() unexpeted error = %v", err)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewTextQuery() = %v, want %v", got, tt.want)
}
})
}
}
func TestColumnComparisonQuery_comp(t *testing.T) {
type fields struct {
Column Column
ColumnCompare Column
Compare ColumnComparison
}
type want struct {
query interface{}
isNil bool
}
tests := []struct {
name string
fields fields
want want
}{
{
name: "equals",
fields: fields{
Column: testCol,
ColumnCompare: testCol2,
Compare: ColumnEquals,
},
want: want{
query: sq.Expr("test_table.test_col = test_table2.test_col2"),
},
},
{
name: "not equals",
fields: fields{
Column: testCol,
ColumnCompare: testCol2,
Compare: ColumnNotEquals,
},
want: want{
query: sq.Expr("test_table.test_col != test_table2.test_col2"),
},
},
{
name: "too high comparison",
fields: fields{
Column: testCol,
ColumnCompare: testCol2,
Compare: columnCompareMax,
},
want: want{
isNil: true,
},
},
{
name: "too low comparison",
fields: fields{
Column: testCol,
ColumnCompare: testCol2,
Compare: -1,
},
want: want{
isNil: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &ColumnComparisonQuery{
Column1: tt.fields.Column,
Column2: tt.fields.ColumnCompare,
Compare: tt.fields.Compare,
}
query := s.comp()
if query == nil && tt.want.isNil {
return
} else if tt.want.isNil && query != nil {
t.Error("query should not be nil")
}
if !reflect.DeepEqual(query, tt.want.query) {
t.Errorf("wrong query: want: %v, (%T), got: %v, (%T)", tt.want.query, tt.want.query, query, query)
}
})
}
}
func TestNewListQuery(t *testing.T) {
type args struct {
column Column
data interface{}
compare ListComparison
}
tests := []struct {
name string
args args
want *ListQuery
wantErr func(error) bool
}{
{
name: "too low compare",
args: args{
column: testCol,
data: []interface{}{"hurst"},
compare: -1,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrInvalidCompare)
},
},
{
name: "too high compare",
args: args{
column: testCol,
data: []interface{}{"hurst"},
compare: listCompareMax,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrInvalidCompare)
},
},
{
name: "no column",
args: args{
column: Column{},
data: []interface{}{"hurst"},
compare: ListIn,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "no column name",
args: args{
column: testNoCol,
data: []interface{}{"hurst"},
compare: ListIn,
},
wantErr: func(err error) bool {
return errors.Is(err, ErrMissingColumn)
},
},
{
name: "correct slice",
args: args{
column: testCol,
data: []interface{}{"hurst"},
compare: ListIn,
},
want: &ListQuery{
Column: testCol,
Data: []interface{}{"hurst"},
Compare: ListIn,
},
},
{
name: "correct",
args: args{
column: testCol,
data: &SubSelect{Column: testCol, Queries: []SearchQuery{&TextQuery{testCol, "horst1", TextEquals}}},
compare: ListIn,
},
want: &ListQuery{
Column: testCol,
Data: &SubSelect{Column: testCol, Queries: []SearchQuery{&TextQuery{testCol, "horst1", TextEquals}}},
Compare: ListIn,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewListQuery(tt.args.column, tt.args.data, tt.args.compare)
if err != nil && tt.wantErr == nil {
t.Errorf("NewTextQuery() no error expected got %v", err)
return
} else if tt.wantErr != nil && !tt.wantErr(err) {
t.Errorf("NewTextQuery() unexpeted error = %v", err)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewTextQuery() = %v, want %v", got, tt.want)
}
})
}
}
func TestListQuery_comp(t *testing.T) {
type fields struct {
Column Column
Data interface{}
Compare ListComparison
}
type want struct {
query interface{}
isNil bool
}
tests := []struct {
name string
fields fields
want want
}{
{
name: "in list one element",
fields: fields{
Column: testCol,
Data: []interface{}{"hurst"},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []interface{}{"hurst"}},
},
},
{
name: "in list three elements",
fields: fields{
Column: testCol,
Data: []interface{}{"hurst1", "hurst2", "hurst3"},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []interface{}{"hurst1", "hurst2", "hurst3"}},
},
},
{
name: "in string list one element",
fields: fields{
Column: testCol,
Data: []string{"hurst"},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []string{"hurst"}},
},
},
{
name: "in string list three elements",
fields: fields{
Column: testCol,
Data: []string{"hurst1", "hurst2", "hurst3"},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []string{"hurst1", "hurst2", "hurst3"}},
},
},
{
name: "in int list one element",
fields: fields{
Column: testCol,
Data: []int{1},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []int{1}},
},
},
{
name: "in int list three elements",
fields: fields{
Column: testCol,
Data: []int{1, 2, 3},
Compare: ListIn,
},
want: want{
query: sq.Eq{"test_table.test_col": []int{1, 2, 3}},
},
},
{
name: "in subquery text",
fields: fields{
Column: testCol,
Data: &SubSelect{Column: testCol, Queries: []SearchQuery{&TextQuery{testCol, "horst", TextEquals}}},
Compare: ListIn,
},
want: want{
query: sq.Expr("test_table.test_col IN ( SELECT test_table.test_col FROM test_table WHERE test_table.test_col = ? )", "horst"),
},
},
{
name: "in subquery number",
fields: fields{
Column: testCol,
Data: &SubSelect{Column: testCol, Queries: []SearchQuery{&NumberQuery{testCol, 1, NumberEquals}}},
Compare: ListIn,
},
want: want{
query: sq.Expr("test_table.test_col IN ( SELECT test_table.test_col FROM test_table WHERE test_table.test_col = ? )", 1),
},
},
{
name: "in subquery column",
fields: fields{
Column: testCol,
Data: &SubSelect{Column: testCol, Queries: []SearchQuery{&ColumnComparisonQuery{testCol, ColumnEquals, testCol2}}},
Compare: ListIn,
},
want: want{
query: sq.Expr("test_table.test_col IN ( SELECT test_table.test_col FROM test_table WHERE test_table.test_col = test_table2.test_col2 )"),
},
},
{
name: "too high comparison",
fields: fields{
Column: testCol,
Data: []interface{}{"hurst"},
Compare: listCompareMax,
},
want: want{
isNil: true,
},
},
{
name: "too low comparison",
fields: fields{
Column: testCol,
Data: []interface{}{"hurst"},
Compare: -1,
},
want: want{
isNil: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &ListQuery{
Column: tt.fields.Column,
Data: tt.fields.Data,
Compare: tt.fields.Compare,
}
query := s.comp()
if query == nil && tt.want.isNil {
return
} else if tt.want.isNil && query != nil {
t.Error("query should not be nil")
}
if !reflect.DeepEqual(query, tt.want.query) {
t.Errorf("wrong query: want: %v, (%T), got: %v, (%T)", tt.want.query, tt.want.query, query, query)
}
})
}
}
func TestNewTextQuery(t *testing.T) {
type args struct {
column Column