LikeCondition.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package core
  2. import (
  3. "strings"
  4. )
  5. type LikeCondition struct {
  6. Field string
  7. Pattern string
  8. CaseSensitive bool
  9. }
  10. func Like(field string, pattern string) Condition {
  11. return LikeCondition{Field: field, Pattern: pattern, CaseSensitive: true}
  12. }
  13. func ILike(field string, pattern string) Condition {
  14. return LikeCondition{Field: field, Pattern: pattern, CaseSensitive: false}
  15. }
  16. func (c LikeCondition) Fields() []string {
  17. return []string{c.Field}
  18. }
  19. func (c LikeCondition) Match(row []byte, table *Table) bool {
  20. fieldIdx := table.findFieldIndex(c.Field)
  21. if fieldIdx < 0 {
  22. return false
  23. }
  24. // v9 起字符串列【按实际长度】存储, 不能按声明宽度取 —— 那会把后面几列的内容也一并
  25. // 切进来 (旧实现按 Width 读, 是定长时代的写法)。堆引用列 (动态列 / 值级溢出列)
  26. // 行内只有 6B, 必须先解引用拿回内容。
  27. start, end, ok := table.getVersionedRange(row, fieldIdx)
  28. if !ok {
  29. return false
  30. }
  31. seg := row[start:end]
  32. if table.columnRefTagged(row, fieldIdx) {
  33. if data, ok := table.derefHeapSeg(seg); ok {
  34. seg = data
  35. } else {
  36. seg = nil // 空引用 / 读取失败 → 空内容
  37. }
  38. }
  39. stored := strings.TrimRight(string(seg), "\x00")
  40. // 模式匹配
  41. if !c.CaseSensitive {
  42. stored = strings.ToLower(stored)
  43. pattern := strings.ToLower(c.Pattern)
  44. return likeMatch(stored, pattern)
  45. }
  46. return likeMatch(stored, c.Pattern)
  47. }
  48. // likeMatch 简单的 LIKE 模式匹配(支持 % 和 _)
  49. func likeMatch(str, pattern string) bool {
  50. // 将 LIKE 模式转换为简单的通配符匹配
  51. // % 匹配任意字符序列(包括空序列)
  52. // _ 匹配任意单个字符
  53. // 简化实现:使用 strings.Contains 处理 %
  54. parts := strings.Split(pattern, "%")
  55. if len(parts) == 1 {
  56. // 没有 %,直接比较
  57. return str == pattern
  58. }
  59. // 检查前缀
  60. if parts[0] != "" && !strings.HasPrefix(str, parts[0]) {
  61. return false
  62. }
  63. // 检查后缀
  64. if parts[len(parts)-1] != "" && !strings.HasSuffix(str, parts[len(parts)-1]) {
  65. return false
  66. }
  67. // 检查中间部分
  68. current := str
  69. if parts[0] != "" {
  70. current = current[len(parts[0]):]
  71. }
  72. for i := 1; i < len(parts); i++ {
  73. idx := strings.Index(current, parts[i])
  74. if idx == -1 {
  75. return false
  76. }
  77. current = current[idx+len(parts[i]):]
  78. }
  79. return true
  80. }