Make tag searches case insensitive
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
9adb872985
commit
5a93761af7
4 changed files with 39 additions and 26 deletions
|
|
@ -9,12 +9,13 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/mattn/go-sqlite3"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
"github.com/cloudbase/garm/util"
|
||||
"github.com/mattn/go-sqlite3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (s *sqlDatabase) CreateFileObject(ctx context.Context, name string, size int64, tags []string, reader io.Reader) (fileObjParam params.FileObject, err error) {
|
||||
|
|
@ -76,7 +77,6 @@ func (s *sqlDatabase) CreateFileObject(ctx context.Context, name string, size in
|
|||
sha256sum = hex.EncodeToString(hasher.Sum(nil))
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return params.FileObject{}, fmt.Errorf("failed to write blob: %w", err)
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ func (s *sqlDatabase) CreateFileObject(ctx context.Context, name string, size in
|
|||
return s.sqlFileObjectToCommonParams(fileObj), nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateFileObject(ctx context.Context, objID uint, param params.UpdateFileObjectParams) (fileObjParam params.FileObject, err error) {
|
||||
func (s *sqlDatabase) UpdateFileObject(_ context.Context, objID uint, param params.UpdateFileObjectParams) (fileObjParam params.FileObject, err error) {
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.FileObject{}, fmt.Errorf("failed to validate update params: %w", err)
|
||||
}
|
||||
|
|
@ -160,7 +160,6 @@ func (s *sqlDatabase) UpdateFileObject(ctx context.Context, objID uint, param pa
|
|||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return params.FileObject{}, err
|
||||
}
|
||||
|
|
@ -168,7 +167,7 @@ func (s *sqlDatabase) UpdateFileObject(ctx context.Context, objID uint, param pa
|
|||
return s.sqlFileObjectToCommonParams(fileObj), nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) DeleteFileObject(ctx context.Context, objID uint) (err error) {
|
||||
func (s *sqlDatabase) DeleteFileObject(_ context.Context, objID uint) (err error) {
|
||||
var fileObjParam params.FileObject
|
||||
var noop bool
|
||||
defer func() {
|
||||
|
|
@ -203,7 +202,7 @@ func (s *sqlDatabase) DeleteFileObject(ctx context.Context, objID uint) (err err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetFileObject(ctx context.Context, objID uint) (params.FileObject, error) {
|
||||
func (s *sqlDatabase) GetFileObject(_ context.Context, objID uint) (params.FileObject, error) {
|
||||
var fileObj FileObject
|
||||
if err := s.conn.Preload("TagsList").Where("id = ?", objID).Omit("content").First(&fileObj).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
|
@ -214,7 +213,7 @@ func (s *sqlDatabase) GetFileObject(ctx context.Context, objID uint) (params.Fil
|
|||
return s.sqlFileObjectToCommonParams(fileObj), nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) SearchFileObjectByTags(ctx context.Context, tags []string, page, pageSize uint64) (params.FileObjectPaginatedResponse, error) {
|
||||
func (s *sqlDatabase) SearchFileObjectByTags(_ context.Context, tags []string, page, pageSize uint64) (params.FileObjectPaginatedResponse, error) {
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
|
@ -298,7 +297,6 @@ func (s *sqlDatabase) OpenFileObjectContent(ctx context.Context, objID uint) (io
|
|||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, fmt.Errorf("failed to open blob for reading: %w", err)
|
||||
|
|
@ -326,7 +324,7 @@ func (b *blobReadCloser) Close() error {
|
|||
return connErr
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) ListFileObjects(ctx context.Context, page, pageSize uint64) (params.FileObjectPaginatedResponse, error) {
|
||||
func (s *sqlDatabase) ListFileObjects(_ context.Context, page, pageSize uint64) (params.FileObjectPaginatedResponse, error) {
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ func (s *FileStoreTestSuite) TestUpdateFileObjectName() {
|
|||
s.Require().Nil(err)
|
||||
s.Require().Equal(newName, updated.Name)
|
||||
s.Require().Equal(s.Fixtures.FileObjects[0].ID, updated.ID)
|
||||
s.Require().Equal(s.Fixtures.FileObjects[0].Size, updated.Size) // Size should not change
|
||||
s.Require().Equal(s.Fixtures.FileObjects[0].Size, updated.Size) // Size should not change
|
||||
s.Require().Equal(s.Fixtures.FileObjects[0].SHA256, updated.SHA256) // SHA256 should not change
|
||||
|
||||
// Verify the change persists
|
||||
|
|
@ -543,27 +543,42 @@ func (s *FileStoreTestSuite) TestSearchFileObjectByTagsAllTagsRequired() {
|
|||
s.Require().True(foundIDs[file2.ID])
|
||||
}
|
||||
|
||||
func (s *FileStoreTestSuite) TestSearchFileObjectByTagsCaseSensitive() {
|
||||
// Test case sensitivity of tag search
|
||||
func (s *FileStoreTestSuite) TestSearchFileObjectByTagsCaseInsensitive() {
|
||||
// Test case insensitivity of tag search (COLLATE NOCASE)
|
||||
content1 := []byte("File with lowercase tag")
|
||||
file1, err := s.Store.CreateFileObject(s.ctx, "case-test-1.txt", int64(len(content1)), []string{"lowercase"}, bytes.NewReader(content1))
|
||||
file1, err := s.Store.CreateFileObject(s.ctx, "case-test-1.txt", int64(len(content1)), []string{"TestTag"}, bytes.NewReader(content1))
|
||||
s.Require().Nil(err)
|
||||
|
||||
content2 := []byte("File with UPPERCASE tag")
|
||||
file2, err := s.Store.CreateFileObject(s.ctx, "case-test-2.txt", int64(len(content2)), []string{"UPPERCASE"}, bytes.NewReader(content2))
|
||||
file2, err := s.Store.CreateFileObject(s.ctx, "case-test-2.txt", int64(len(content2)), []string{"TESTTAG"}, bytes.NewReader(content2))
|
||||
s.Require().Nil(err)
|
||||
|
||||
// Search for lowercase - should only return file1
|
||||
result, err := s.Store.SearchFileObjectByTags(s.ctx, []string{"lowercase"}, 1, 10)
|
||||
content3 := []byte("File with MixedCase tag")
|
||||
file3, err := s.Store.CreateFileObject(s.ctx, "case-test-3.txt", int64(len(content3)), []string{"testTAG"}, bytes.NewReader(content3))
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(1, len(result.Results))
|
||||
s.Require().Equal(file1.ID, result.Results[0].ID)
|
||||
|
||||
// Search for UPPERCASE - should only return file2
|
||||
result, err = s.Store.SearchFileObjectByTags(s.ctx, []string{"UPPERCASE"}, 1, 10)
|
||||
// Search for lowercase - should return all files (case insensitive)
|
||||
result, err := s.Store.SearchFileObjectByTags(s.ctx, []string{"testtag"}, 1, 10)
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(1, len(result.Results))
|
||||
s.Require().Equal(file2.ID, result.Results[0].ID)
|
||||
s.Require().Equal(3, len(result.Results), "Should match all case variations")
|
||||
|
||||
foundIDs := make(map[uint]bool)
|
||||
for _, fileObj := range result.Results {
|
||||
foundIDs[fileObj.ID] = true
|
||||
}
|
||||
s.Require().True(foundIDs[file1.ID], "Should find file with 'TestTag'")
|
||||
s.Require().True(foundIDs[file2.ID], "Should find file with 'TESTTAG'")
|
||||
s.Require().True(foundIDs[file3.ID], "Should find file with 'testTAG'")
|
||||
|
||||
// Search for UPPERCASE - should also return all files
|
||||
result, err = s.Store.SearchFileObjectByTags(s.ctx, []string{"TESTTAG"}, 1, 10)
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(3, len(result.Results), "Should match all case variations")
|
||||
|
||||
// Search for MixedCase - should also return all files
|
||||
result, err = s.Store.SearchFileObjectByTags(s.ctx, []string{"TeStTaG"}, 1, 10)
|
||||
s.Require().Nil(err)
|
||||
s.Require().Equal(3, len(result.Results), "Should match all case variations")
|
||||
}
|
||||
|
||||
func (s *FileStoreTestSuite) TestSearchFileObjectByTagsOrderByCreatedAt() {
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ func (FileObject) TableName() string {
|
|||
type FileObjectTag struct {
|
||||
ID uint `gorm:"primaryKey"`
|
||||
FileObjectID uint `gorm:"index:idx_fileobject_tags_doc_id,priority:1;index:idx_fileobject_tags_tag,priority:1;not null"`
|
||||
Tag string `gorm:"type:TEXT;index:idx_fileobject_tags_tag,priority:2;not null"`
|
||||
Tag string `gorm:"type:TEXT COLLATE NOCASE;index:idx_fileobject_tags_tag,priority:2;not null"`
|
||||
}
|
||||
|
||||
// TableName overrides the default table name
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue