github.com/zlyuancn/zstr@v0.0.0-20230412074414-14d6b645962f/repair_sql.go (about)

     1  /*
     2  -------------------------------------------------
     3     Author :       Zhang Fan
     4     date:         2020/7/18
     5     Description :
     6  -------------------------------------------------
     7  */
     8  
     9  package zstr
    10  
    11  import (
    12  	"bytes"
    13  )
    14  
    15  var emptyStrMap = map[int32]struct{}{
    16  	'\f': {},
    17  	'\n': {},
    18  	'\r': {},
    19  	'\t': {},
    20  	'\v': {},
    21  	' ':  {},
    22  	0x85: {},
    23  	0xA0: {},
    24  }
    25  
    26  // 缩进空格
    27  func (m *sqlTemplate) retractAllSpace(s string) string {
    28  	var buff bytes.Buffer
    29  	old := -2
    30  	var ok bool
    31  	for i, v := range []rune(s) {
    32  		if _, ok = emptyStrMap[v]; ok {
    33  			if i-old > 1 {
    34  				buff.WriteByte(' ')
    35  			}
    36  			old = i
    37  		} else {
    38  			buff.WriteRune(v)
    39  		}
    40  	}
    41  
    42  	return buff.String()
    43  }
    44  
    45  var repairSqlTexts = []struct {
    46  	Old     string // 原始数据
    47  	New     string // 新数据
    48  	Retract bool   // 是否缩进
    49  }{
    50  	{"( and", "(", false},
    51  	{"(and", "(", false},
    52  	{"( or", "(", false},
    53  	{"(or", "(", false},
    54  	{"and ( )", "", true},
    55  	{"and ()", "", true},
    56  	{"or ( )", "", true},
    57  	{"or ()", "", true},
    58  	{"where ( )", "where", false},
    59  	{"where ()", "where", false},
    60  	{"where and ", "where ", false},
    61  	{"where or ", "where ", false},
    62  	{"where order by ", "order by ", false},
    63  	{"where group by ", "group by ", false},
    64  	{"where limit ", "limit ", false},
    65  	{"where )", ")", false},
    66  }
    67  var repairSqlSuffixes = []string{
    68  	"where",
    69  	"where ",
    70  	"where;",
    71  	"where ;",
    72  }
    73  
    74  // 修复模板渲染后无效的sql语句
    75  func (m *sqlTemplate) repairSql(sql string) string {
    76  	result := m.retractAllSpace(sql)
    77  
    78  	for _, r := range repairSqlTexts {
    79  		result = m.ReplaceAllIgnoreCase(result, r.Old, r.New)
    80  		if r.Retract {
    81  			result = m.retractAllSpace(result)
    82  		}
    83  	}
    84  	for _, suffix := range repairSqlSuffixes {
    85  		if m.HasSuffixIgnoreCase(result, suffix) {
    86  			result = result[:len(result)-len(suffix)]
    87  			return result
    88  		}
    89  	}
    90  	return result
    91  }
    92  
    93  // 忽略大小写检查字符相等
    94  func (m *sqlTemplate) EqualCharIgnoreCase(c1, c2 int32) bool {
    95  	if c1 == c2 {
    96  		return true
    97  	}
    98  	switch c1 - c2 {
    99  	case 32: // a - A
   100  		return c1 >= 'a' && c1 <= 'z'
   101  	case -32: // A - a
   102  		return c1 >= 'A' && c1 <= 'Z'
   103  	}
   104  	return false
   105  }
   106  
   107  // 忽略大小写检查文本相等
   108  func (m *sqlTemplate) EqualIgnoreCase(s1, s2 string) bool {
   109  	if s1 == s2 {
   110  		return true
   111  	}
   112  
   113  	r1 := []rune(s1)
   114  	r2 := []rune(s2)
   115  	if len(r1) != len(r2) {
   116  		return false
   117  	}
   118  
   119  	for i, r := range r1 {
   120  		if !m.EqualCharIgnoreCase(r, r2[i]) {
   121  			return false
   122  		}
   123  	}
   124  	return true
   125  }
   126  
   127  // 忽略大小写替换所有文本
   128  func (m *sqlTemplate) ReplaceAllIgnoreCase(s, old, new string) string {
   129  	return m.ReplaceIgnoreCase(s, old, new, -1)
   130  }
   131  
   132  // 替换n次忽略大小写匹配的文本
   133  func (m *sqlTemplate) ReplaceIgnoreCase(s, old, new string, n int) string {
   134  	if n == 0 || old == new || old == "" {
   135  		return s
   136  	}
   137  
   138  	ss := []rune(s)
   139  	sub := []rune(old)
   140  	var buff bytes.Buffer
   141  	var num int
   142  	for offset := 0; offset < len(ss); {
   143  		start := m.searchIgnoreCase(ss, sub, offset)
   144  		if start > -1 {
   145  			buff.WriteString(string(ss[offset:start]))
   146  			buff.WriteString(new)
   147  			offset = start + len(sub)
   148  			num++
   149  		}
   150  
   151  		if start == -1 || num == n {
   152  			buff.WriteString(string(ss[offset:]))
   153  			break
   154  		}
   155  	}
   156  	return buff.String()
   157  }
   158  
   159  // 忽略大小写查找第一个匹配sub的文本所在位置, 如果不存在返回-1
   160  func (m *sqlTemplate) searchIgnoreCase(ss []rune, sub []rune, start int) int {
   161  	if len(ss)-start < len(sub) {
   162  		return -1
   163  	}
   164  
   165  	var has bool
   166  	// 查找开头
   167  	for i := start; i < len(ss); i++ {
   168  		if m.EqualCharIgnoreCase(ss[i], sub[0]) {
   169  			start, has = i, true
   170  			break
   171  		}
   172  	}
   173  	if !has || len(ss)-start < len(sub) {
   174  		return -1
   175  	}
   176  	for i := 1; i < len(sub); i++ {
   177  		if !m.EqualCharIgnoreCase(ss[start+i], sub[i]) {
   178  			return m.searchIgnoreCase(ss, sub, start+1)
   179  		}
   180  	}
   181  	return start
   182  }
   183  
   184  // 忽略大小写查找第一个匹配sub的文本所在位置, 如果不存在返回-1
   185  func (m *sqlTemplate) IndexIgnoreCase(s, sub string) int {
   186  	return m.searchIgnoreCase([]rune(s), []rune(sub), 0)
   187  }
   188  
   189  // 忽略大小写查找s是否包含sub
   190  func (m *sqlTemplate) ContainsIgnoreCase(s, sub string) bool {
   191  	return m.IndexIgnoreCase(s, sub) >= 0
   192  }
   193  
   194  // 忽略大小写测试文本s是否以suffix结束
   195  func (m *sqlTemplate) HasSuffixIgnoreCase(s, suffix string) bool {
   196  	return len(s) >= len(suffix) && m.EqualIgnoreCase(s[len(s)-len(suffix):], suffix)
   197  }