Files
chaisql/internal/expr/comparison_test.go
2025-09-20 21:03:29 +05:30

187 lines
5.2 KiB
Go

package expr_test
import (
"testing"
"github.com/chaisql/chai/internal/database"
"github.com/chaisql/chai/internal/environment"
"github.com/chaisql/chai/internal/row"
"github.com/chaisql/chai/internal/testutil"
"github.com/chaisql/chai/internal/types"
)
var envWithRow = environment.New(
nil,
nil,
nil,
database.NewBasicRow(row.NewColumnBuffer().Add("a", types.NewIntegerValue(1))),
)
func TestComparisonExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 = a", types.NewBooleanValue(true), false},
{"1 = NULL", nullLiteral, false},
{"1 = notFound", nullLiteral, true},
{"1 != a", types.NewBooleanValue(false), false},
{"1 != NULL", nullLiteral, false},
{"1 != notFound", nullLiteral, true},
{"1 > a", types.NewBooleanValue(false), false},
{"1 > NULL", nullLiteral, false},
{"1 > notFound", nullLiteral, true},
{"1 >= a", types.NewBooleanValue(true), false},
{"1 >= NULL", nullLiteral, false},
{"1 >= notFound", nullLiteral, true},
{"1 < a", types.NewBooleanValue(false), false},
{"1 < NULL", nullLiteral, false},
{"1 < notFound", nullLiteral, true},
{"1 <= a", types.NewBooleanValue(true), false},
{"1 <= NULL", nullLiteral, false},
{"1 <= notFound", nullLiteral, true},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}
func TestComparisonINExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 IN (2)", types.NewBooleanValue(false), false},
{"1 IN (1, 2, 3)", types.NewBooleanValue(true), false},
{"2 IN (2.1, 2.2, 2.0)", types.NewBooleanValue(true), false},
{"1 IN (2, 3)", types.NewBooleanValue(false), false},
{"(1) IN (1, 2, 3)", types.NewBooleanValue(true), false},
{"(1) IN (1), (2), (3)", types.NewBooleanValue(true), false},
{"NULL IN (1, 2, NULL)", nullLiteral, false},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}
func TestComparisonNOTINExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 NOT IN (1, 2, 3)", types.NewBooleanValue(false), false},
{"1 NOT IN (2, 3)", types.NewBooleanValue(true), false},
{"(1) NOT IN (1, 2, 3)", types.NewBooleanValue(false), false},
{"NULL NOT IN (1, 2, NULL)", nullLiteral, false},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}
func TestComparisonISExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 IS 1", types.NewBooleanValue(true), false},
{"1 IS 2", types.NewBooleanValue(false), false},
{"1 IS NULL", types.NewBooleanValue(false), false},
{"NULL IS NULL", types.NewBooleanValue(true), false},
{"NULL IS 1", types.NewBooleanValue(false), false},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}
func TestComparisonISNOTExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 IS NOT 1", types.NewBooleanValue(false), false},
{"1 IS NOT 2", types.NewBooleanValue(true), false},
{"1 IS NOT NULL", types.NewBooleanValue(true), false},
{"NULL IS NOT NULL", types.NewBooleanValue(false), false},
{"NULL IS NOT 1", types.NewBooleanValue(true), false},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}
func TestComparisonExprNoObject(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 = a", nullLiteral, true},
{"1 != a", nullLiteral, true},
{"1 > a", nullLiteral, true},
{"1 >= a", nullLiteral, true},
{"1 < a", nullLiteral, true},
{"1 <= a", nullLiteral, true},
{"1 IN (a)", nullLiteral, true},
{"1 IS a", nullLiteral, true},
{"1 IS NOT a", nullLiteral, true},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
var emptyenv environment.Environment
testutil.TestExpr(t, test.expr, &emptyenv, test.res, test.fails)
})
}
})
}
}
func TestComparisonBetweenExpr(t *testing.T) {
tests := []struct {
expr string
res types.Value
fails bool
}{
{"1 BETWEEN 0 AND 2", types.NewBooleanValue(true), false},
{"1 BETWEEN 0 AND 1", types.NewBooleanValue(true), false},
{"1 BETWEEN 1 AND 2", types.NewBooleanValue(true), false},
{"1 BETWEEN NULL AND 2", types.NewNullValue(), false},
{"1 BETWEEN 0 AND 'foo'", types.NewBooleanValue(false), false},
{"1 BETWEEN 'foo' AND 2", types.NewBooleanValue(false), false},
{"1 BETWEEN '1' AND 2", types.NewBooleanValue(false), false},
{"1 BETWEEN CAST('1' AS int) AND 2", types.NewBooleanValue(true), false},
{"1 BETWEEN CAST('1' AS double precision) AND 2", types.NewBooleanValue(true), false},
}
for _, test := range tests {
t.Run(test.expr, func(t *testing.T) {
testutil.TestExpr(t, test.expr, envWithRow, test.res, test.fails)
})
}
}