Implement TextOperationContains and TextOperationContainsWithIgnoreCase

This commit is contained in:
Marco Ardizzone
2025-09-19 18:43:56 +02:00
parent e29933b905
commit c17eae1fac
2 changed files with 124 additions and 6 deletions

View File

@@ -34,15 +34,21 @@ const (
TextOperationStartsWith
// TextOperationStartsWithIgnoreCase checks if the first string starts with the second, ignoring case.
TextOperationStartsWithIgnoreCase
// TextOperationContains checks if the first string contains the second
TextOperationContains
// TextOperationContains checks if the first string contains the second, ignoring case.
TextOperationContainsWithIgnoreCase
)
var textOperations = map[TextOperation]string{
TextOperationEqual: " = ",
TextOperationEqualIgnoreCase: " LIKE ",
TextOperationNotEqual: " <> ",
TextOperationNotEqualIgnoreCase: " NOT LIKE ",
TextOperationStartsWith: " LIKE ",
TextOperationStartsWithIgnoreCase: " LIKE ",
TextOperationEqual: " = ",
TextOperationEqualIgnoreCase: " LIKE ",
TextOperationNotEqual: " <> ",
TextOperationNotEqualIgnoreCase: " NOT LIKE ",
TextOperationStartsWith: " LIKE ",
TextOperationStartsWithIgnoreCase: " LIKE ",
TextOperationContains: " LIKE ",
TextOperationContainsWithIgnoreCase: " ILIKE ",
}
func writeTextOperation[T Text](builder *StatementBuilder, col Column, op TextOperation, value T) {
@@ -75,6 +81,12 @@ func writeTextOperation[T Text](builder *StatementBuilder, col Column, op TextOp
builder.WriteArg(value)
builder.WriteString(")")
builder.WriteString(" || '%'")
case TextOperationContains, TextOperationContainsWithIgnoreCase:
col.WriteQualified(builder)
builder.WriteString(textOperations[op])
builder.WriteString("'%' || ")
builder.WriteArg(value)
builder.WriteString(" || '%'")
default:
panic("unsupported text operation")
}

View File

@@ -0,0 +1,106 @@
package database
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWriteTextOperation(t *testing.T) {
t.Parallel()
tests := []struct {
name string
col Column
op TextOperation
value string
expected string
args []any
}{
{
name: "Equal",
col: NewColumn("test", "col"),
op: TextOperationEqual,
value: "value",
expected: "test.col = $1",
args: []any{"value"},
},
{
name: "NotEqual",
col: NewColumn("test", "col"),
op: TextOperationNotEqual,
value: "value",
expected: "test.col <> $1",
args: []any{"value"},
},
{
name: "EqualIgnoreCase",
col: NewColumn("test", "col"),
op: TextOperationEqualIgnoreCase,
value: "value",
expected: "LOWER(test.col) LIKE LOWER($1)",
args: []any{"value"},
},
{
name: "NotEqualIgnoreCase",
col: NewColumn("test", "col"),
op: TextOperationNotEqualIgnoreCase,
value: "value",
expected: "LOWER(test.col) NOT LIKE LOWER($1)",
args: []any{"value"},
},
{
name: "StartsWith",
col: NewColumn("test", "col"),
op: TextOperationStartsWith,
value: "value",
expected: "test.col LIKE $1 || '%'",
args: []any{"value"},
},
{
name: "StartsWithIgnoreCase",
col: NewColumn("test", "col"),
op: TextOperationStartsWithIgnoreCase,
value: "value",
expected: "LOWER(test.col) LIKE LOWER($1) || '%'",
args: []any{"value"},
},
{
name: "Contains",
col: NewColumn("test", "col"),
op: TextOperationContains,
value: "value",
expected: "test.col LIKE '%' || $1 || '%'",
args: []any{"value"},
},
{
name: "ContainsIgnoreCase",
col: NewColumn("test", "col"),
op: TextOperationContainsWithIgnoreCase,
value: "value",
expected: "test.col ILIKE '%' || $1 || '%'",
args: []any{"value"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
builder := &StatementBuilder{}
writeTextOperation(builder, tt.col, tt.op, tt.value)
assert.Equal(t, tt.expected, builder.String())
assert.Equal(t, tt.args, builder.Args())
})
}
t.Run("panic on invalid operation", func(t *testing.T) {
t.Parallel()
defer func() {
require.NotNil(t, recover())
}()
builder := &StatementBuilder{}
writeTextOperation(builder, NewColumn("test", "col"), TextOperation(99), "value")
})
}