LikeCondition.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. offset, ok := table.getVersionedOffset(row, fieldIdx)
  25. if !ok {
  26. return false
  27. }
  28. fieldInfo := table.Field[fieldIdx]
  29. // 读取字符串值; 宽度取列声明的宽度 (含字符串宽度码), 否则宽字符串列会被切短
  30. size := int(fieldInfo.Width())
  31. if size <= 0 || int(offset)+size > len(row) {
  32. return false
  33. }
  34. stored := strings.TrimRight(string(row[offset:int(offset)+size]), "\x00")
  35. // 模式匹配
  36. if !c.CaseSensitive {
  37. stored = strings.ToLower(stored)
  38. pattern := strings.ToLower(c.Pattern)
  39. return likeMatch(stored, pattern)
  40. }
  41. return likeMatch(stored, c.Pattern)
  42. }
  43. // likeMatch 简单的 LIKE 模式匹配(支持 % 和 _)
  44. func likeMatch(str, pattern string) bool {
  45. // 将 LIKE 模式转换为简单的通配符匹配
  46. // % 匹配任意字符序列(包括空序列)
  47. // _ 匹配任意单个字符
  48. // 简化实现:使用 strings.Contains 处理 %
  49. parts := strings.Split(pattern, "%")
  50. if len(parts) == 1 {
  51. // 没有 %,直接比较
  52. return str == pattern
  53. }
  54. // 检查前缀
  55. if parts[0] != "" && !strings.HasPrefix(str, parts[0]) {
  56. return false
  57. }
  58. // 检查后缀
  59. if parts[len(parts)-1] != "" && !strings.HasSuffix(str, parts[len(parts)-1]) {
  60. return false
  61. }
  62. // 检查中间部分
  63. current := str
  64. if parts[0] != "" {
  65. current = current[len(parts[0]):]
  66. }
  67. for i := 1; i < len(parts); i++ {
  68. idx := strings.Index(current, parts[i])
  69. if idx == -1 {
  70. return false
  71. }
  72. current = current[idx+len(parts[i]):]
  73. }
  74. return true
  75. }