| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package core
- import (
- "strings"
- )
- type LikeCondition struct {
- Field string
- Pattern string
- CaseSensitive bool
- }
- func Like(field string, pattern string) Condition {
- return LikeCondition{Field: field, Pattern: pattern, CaseSensitive: true}
- }
- func ILike(field string, pattern string) Condition {
- return LikeCondition{Field: field, Pattern: pattern, CaseSensitive: false}
- }
- func (c LikeCondition) Fields() []string {
- return []string{c.Field}
- }
- func (c LikeCondition) Match(row []byte, table *Table) bool {
- fieldIdx := table.findFieldIndex(c.Field)
- if fieldIdx < 0 {
- return false
- }
- // v9 起字符串列【按实际长度】存储, 不能按声明宽度取 —— 那会把后面几列的内容也一并
- // 切进来 (旧实现按 Width 读, 是定长时代的写法)。堆引用列 (动态列 / 值级溢出列)
- // 行内只有 6B, 必须先解引用拿回内容。
- start, end, ok := table.getVersionedRange(row, fieldIdx)
- if !ok {
- return false
- }
- seg := row[start:end]
- if table.columnRefTagged(row, fieldIdx) {
- if data, ok := table.derefHeapSeg(seg); ok {
- seg = data
- } else {
- seg = nil // 空引用 / 读取失败 → 空内容
- }
- }
- stored := strings.TrimRight(string(seg), "\x00")
- // 模式匹配
- if !c.CaseSensitive {
- stored = strings.ToLower(stored)
- pattern := strings.ToLower(c.Pattern)
- return likeMatch(stored, pattern)
- }
- return likeMatch(stored, c.Pattern)
- }
- // likeMatch 简单的 LIKE 模式匹配(支持 % 和 _)
- func likeMatch(str, pattern string) bool {
- // 将 LIKE 模式转换为简单的通配符匹配
- // % 匹配任意字符序列(包括空序列)
- // _ 匹配任意单个字符
- // 简化实现:使用 strings.Contains 处理 %
- parts := strings.Split(pattern, "%")
- if len(parts) == 1 {
- // 没有 %,直接比较
- return str == pattern
- }
- // 检查前缀
- if parts[0] != "" && !strings.HasPrefix(str, parts[0]) {
- return false
- }
- // 检查后缀
- if parts[len(parts)-1] != "" && !strings.HasSuffix(str, parts[len(parts)-1]) {
- return false
- }
- // 检查中间部分
- current := str
- if parts[0] != "" {
- current = current[len(parts[0]):]
- }
- for i := 1; i < len(parts); i++ {
- idx := strings.Index(current, parts[i])
- if idx == -1 {
- return false
- }
- current = current[idx+len(parts[i]):]
- }
- return true
- }
|