pkg/query/logical/expr_literal.go (356 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package logical
import (
"fmt"
"math"
"strconv"
"strings"
"golang.org/x/exp/slices"
databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
"github.com/apache/skywalking-banyandb/pkg/convert"
"github.com/apache/skywalking-banyandb/pkg/index"
"github.com/apache/skywalking-banyandb/pkg/logger"
)
var (
_ LiteralExpr = (*int64Literal)(nil)
_ ComparableExpr = (*int64Literal)(nil)
)
type int64Literal struct {
int64
}
func (i *int64Literal) Field(key index.FieldKey) index.Field {
return index.NewIntField(key, i.int64)
}
func (i *int64Literal) RangeOpts(isUpper bool, includeLower bool, includeUpper bool) index.RangeOpts {
if isUpper {
return index.NewIntRangeOpts(math.MinInt64, i.int64, includeLower, includeUpper)
}
return index.NewIntRangeOpts(i.int64, math.MaxInt64, includeLower, includeUpper)
}
func (i *int64Literal) SubExprs() []LiteralExpr {
return []LiteralExpr{i}
}
func newInt64Literal(val int64) *int64Literal {
return &int64Literal{
int64: val,
}
}
func (i *int64Literal) Compare(other LiteralExpr) (int, bool) {
if o, ok := other.(*int64Literal); ok {
return int(i.int64 - o.int64), true
}
return 0, false
}
func (i *int64Literal) Contains(other LiteralExpr) bool {
if o, ok := other.(*int64Literal); ok {
return i == o
}
if o, ok := other.(*int64ArrLiteral); ok {
if len(o.arr) == 1 && o.arr[0] == i.int64 {
return true
}
}
return false
}
func (i *int64Literal) BelongTo(other LiteralExpr) bool {
if o, ok := other.(*int64Literal); ok {
return i == o
}
if o, ok := other.(*int64ArrLiteral); ok {
return slices.Contains(o.arr, i.int64)
}
return false
}
func (i *int64Literal) Bytes() [][]byte {
return [][]byte{convert.Int64ToBytes(i.int64)}
}
func (i *int64Literal) Equal(expr Expr) bool {
if other, ok := expr.(*int64Literal); ok {
return other.int64 == i.int64
}
return false
}
func (i *int64Literal) String() string {
return strconv.FormatInt(i.int64, 10)
}
func (i *int64Literal) Elements() []string {
return []string{strconv.FormatInt(i.int64, 10)}
}
var (
_ LiteralExpr = (*int64ArrLiteral)(nil)
_ ComparableExpr = (*int64ArrLiteral)(nil)
)
type int64ArrLiteral struct {
arr []int64
}
func (i *int64ArrLiteral) Field(_ index.FieldKey) index.Field {
logger.Panicf("unsupported generate an index field for int64 array")
return index.Field{}
}
func (i *int64ArrLiteral) RangeOpts(_ bool, _ bool, _ bool) index.RangeOpts {
logger.Panicf("unsupported generate an index range opts for int64 array")
return index.RangeOpts{}
}
func (i *int64ArrLiteral) SubExprs() []LiteralExpr {
exprs := make([]LiteralExpr, 0, len(i.arr))
for _, v := range i.arr {
exprs = append(exprs, newInt64Literal(v))
}
return exprs
}
func newInt64ArrLiteral(val []int64) *int64ArrLiteral {
return &int64ArrLiteral{
arr: val,
}
}
func (i *int64ArrLiteral) Compare(other LiteralExpr) (int, bool) {
if o, ok := other.(*int64ArrLiteral); ok {
return 0, slices.Equal(i.arr, o.arr)
}
return 0, false
}
func (i *int64ArrLiteral) Contains(other LiteralExpr) bool {
if o, ok := other.(*int64Literal); ok {
return slices.Contains(i.arr, o.int64)
}
if o, ok := other.(*int64ArrLiteral); ok {
for _, v := range o.arr {
if !slices.Contains(i.arr, v) {
return false
}
}
return true
}
return false
}
func (i *int64ArrLiteral) BelongTo(other LiteralExpr) bool {
if o, ok := other.(*int64Literal); ok {
if len(i.arr) == 1 && i.arr[0] == o.int64 {
return true
}
return false
}
if o, ok := other.(*int64ArrLiteral); ok {
for _, v := range i.arr {
if !slices.Contains(o.arr, v) {
return false
}
}
return true
}
return false
}
func (i *int64ArrLiteral) Bytes() [][]byte {
b := make([][]byte, 0, len(i.arr))
for _, i := range i.arr {
b = append(b, convert.Int64ToBytes(i))
}
return b
}
func (i *int64ArrLiteral) Equal(expr Expr) bool {
if other, ok := expr.(*int64ArrLiteral); ok {
return slices.Equal(other.arr, i.arr)
}
return false
}
func (i *int64ArrLiteral) String() string {
return fmt.Sprintf("%v", i.arr)
}
func (i *int64ArrLiteral) Elements() []string {
var elements []string
for _, v := range i.arr {
elements = append(elements, strconv.FormatInt(v, 10))
}
return elements
}
var (
_ LiteralExpr = (*strLiteral)(nil)
_ ComparableExpr = (*strLiteral)(nil)
defaultUpper = convert.Uint64ToBytes(math.MaxUint64)
defaultLower = convert.Uint64ToBytes(0)
)
type strLiteral struct {
string
}
func (s *strLiteral) Field(key index.FieldKey) index.Field {
return index.NewStringField(key, s.string)
}
func (s *strLiteral) RangeOpts(isUpper bool, includeLower bool, includeUpper bool) index.RangeOpts {
if isUpper {
return index.NewStringRangeOpts(convert.BytesToString(defaultLower), s.string, includeLower, includeUpper)
}
return index.NewStringRangeOpts(s.string, convert.BytesToString(defaultUpper), includeLower, includeUpper)
}
func (s *strLiteral) SubExprs() []LiteralExpr {
return []LiteralExpr{s}
}
func (s *strLiteral) Compare(other LiteralExpr) (int, bool) {
if o, ok := other.(*strLiteral); ok {
return strings.Compare(s.string, o.string), true
}
return 0, false
}
func (s *strLiteral) Contains(other LiteralExpr) bool {
if o, ok := other.(*strLiteral); ok {
return s == o
}
if o, ok := other.(*strArrLiteral); ok {
if len(o.arr) == 1 && o.arr[0] == s.string {
return true
}
}
return false
}
func (s *strLiteral) BelongTo(other LiteralExpr) bool {
if o, ok := other.(*strLiteral); ok {
return s == o
}
if o, ok := other.(*strArrLiteral); ok {
return slices.Contains(o.arr, s.string)
}
return false
}
func (s *strLiteral) Bytes() [][]byte {
return [][]byte{[]byte(s.string)}
}
func (s *strLiteral) Equal(expr Expr) bool {
if other, ok := expr.(*strLiteral); ok {
return other.string == s.string
}
return false
}
func str(str string) LiteralExpr {
return &strLiteral{str}
}
func (s *strLiteral) String() string {
return s.string
}
func (s *strLiteral) Elements() []string {
return []string{s.string}
}
var (
_ LiteralExpr = (*strArrLiteral)(nil)
_ ComparableExpr = (*strArrLiteral)(nil)
)
type strArrLiteral struct {
arr []string
}
func (s *strArrLiteral) Field(_ index.FieldKey) index.Field {
logger.Panicf("unsupported generate an index field for string array")
return index.Field{}
}
func (s *strArrLiteral) RangeOpts(_ bool, _ bool, _ bool) index.RangeOpts {
logger.Panicf("unsupported generate an index range opts for string array")
return index.RangeOpts{}
}
func (s *strArrLiteral) SubExprs() []LiteralExpr {
exprs := make([]LiteralExpr, 0, len(s.arr))
for _, v := range s.arr {
exprs = append(exprs, str(v))
}
return exprs
}
func newStrArrLiteral(val []string) *strArrLiteral {
return &strArrLiteral{
arr: val,
}
}
func (s *strArrLiteral) Compare(other LiteralExpr) (int, bool) {
if o, ok := other.(*strArrLiteral); ok {
return 0, StringSlicesEqual(s.arr, o.arr)
}
return 0, false
}
func (s *strArrLiteral) Contains(other LiteralExpr) bool {
if o, ok := other.(*strLiteral); ok {
return slices.Contains(s.arr, o.string)
}
if o, ok := other.(*strArrLiteral); ok {
for _, v := range o.arr {
if !slices.Contains(s.arr, v) {
return false
}
}
return true
}
return false
}
func (s *strArrLiteral) BelongTo(other LiteralExpr) bool {
if o, ok := other.(*strLiteral); ok {
if len(s.arr) == 1 && s.arr[0] == o.string {
return true
}
return false
}
if o, ok := other.(*strArrLiteral); ok {
for _, v := range s.arr {
if !slices.Contains(o.arr, v) {
return false
}
}
return true
}
return false
}
func (s *strArrLiteral) Bytes() [][]byte {
b := make([][]byte, 0, len(s.arr))
for _, str := range s.arr {
b = append(b, []byte(str))
}
return b
}
func (s *strArrLiteral) Equal(expr Expr) bool {
if other, ok := expr.(*strArrLiteral); ok {
return slices.Equal(other.arr, s.arr)
}
return false
}
func (s *strArrLiteral) String() string {
return fmt.Sprintf("%v", s.arr)
}
func (s *strArrLiteral) Elements() []string {
return s.arr
}
var (
_ LiteralExpr = (*nullLiteral)(nil)
_ ComparableExpr = (*nullLiteral)(nil)
nullLiteralExpr = &nullLiteral{}
nullIndexField = index.Field{}
nullRangeOpts = index.RangeOpts{}
)
type nullLiteral struct{}
func (s *nullLiteral) Field(_ index.FieldKey) index.Field {
return nullIndexField
}
func (s *nullLiteral) RangeOpts(_ bool, _ bool, _ bool) index.RangeOpts {
return nullRangeOpts
}
func (s *nullLiteral) SubExprs() []LiteralExpr {
panic("unimplemented")
}
func newNullLiteral() *nullLiteral {
return nullLiteralExpr
}
func (s nullLiteral) Compare(_ LiteralExpr) (int, bool) {
return 0, false
}
func (s nullLiteral) BelongTo(_ LiteralExpr) bool {
return false
}
func (s nullLiteral) Contains(_ LiteralExpr) bool {
return false
}
func (s nullLiteral) Bytes() [][]byte {
return nil
}
func (s nullLiteral) Equal(_ Expr) bool {
return false
}
func (s nullLiteral) DataType() int32 {
return int32(databasev1.TagType_TAG_TYPE_UNSPECIFIED)
}
func (s nullLiteral) String() string {
return "null"
}
func (s nullLiteral) Elements() []string {
return []string{"null"}
}