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 }