vitess.io/vitess@v0.16.2/go/vt/sqlparser/predicate_rewriting_test.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqlparser 18 19 import ( 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestSimplifyExpression(in *testing.T) { 27 tests := []struct { 28 in string 29 expected string 30 }{{ 31 in: "not (not A = 3)", 32 expected: "A = 3", 33 }, { 34 in: "not (A = 3 and B = 2)", 35 expected: "not A = 3 or not B = 2", 36 }, { 37 in: "not (A = 3 or B = 2)", 38 expected: "not A = 3 and not B = 2", 39 }, { 40 in: "A xor B", 41 expected: "(A or B) and not (A and B)", 42 }, { 43 in: "(A and B) or C", 44 expected: "(A or C) and (B or C)", 45 }, { 46 in: "C or (A and B)", 47 expected: "(C or A) and (C or B)", 48 }, { 49 in: "A and A", 50 expected: "A", 51 }, { 52 in: "A OR A", 53 expected: "A", 54 }, { 55 in: "A OR (A AND B)", 56 expected: "A", 57 }, { 58 in: "A OR (B AND A)", 59 expected: "A", 60 }, { 61 in: "(A AND B) OR A", 62 expected: "A", 63 }, { 64 in: "(B AND A) OR A", 65 expected: "A", 66 }, { 67 in: "(A and B) and (B and A)", 68 expected: "A and B", 69 }, { 70 in: "(A or B) and A", 71 expected: "A", 72 }, { 73 in: "A and (A or B)", 74 expected: "A", 75 }, { 76 in: "(A and B) OR (A and C)", 77 expected: "A and (B or C)", 78 }, { 79 in: "(A and B) OR (C and A)", 80 expected: "A and (B or C)", 81 }, { 82 in: "(B and A) OR (A and C)", 83 expected: "A and (B or C)", 84 }, { 85 in: "(B and A) OR (C and A)", 86 expected: "A and (B or C)", 87 }} 88 89 for _, tc := range tests { 90 in.Run(tc.in, func(t *testing.T) { 91 expr, err := ParseExpr(tc.in) 92 require.NoError(t, err) 93 94 expr, didRewrite := simplifyExpression(expr) 95 assert.True(t, didRewrite.changed()) 96 assert.Equal(t, tc.expected, String(expr)) 97 }) 98 } 99 } 100 101 func TestRewritePredicate(in *testing.T) { 102 tests := []struct { 103 in string 104 expected string 105 }{{ 106 in: "A xor B", 107 expected: "(A or B) and (not A or not B)", 108 }, { 109 in: "(A and B) and (B and A) and (B and A) and (A and B)", 110 expected: "A and B", 111 }, { 112 in: "((A and B) OR (A and C) OR (A and D)) and E and F", 113 expected: "A and (B or C or D) and E and F", 114 }, { 115 in: "(A and B) OR (A and C)", 116 expected: "A and (B or C)", 117 }, { 118 in: "(A and B) OR (C and A)", 119 expected: "A and (B or C)", 120 }, { 121 in: "(B and A) OR (A and C)", 122 expected: "A and (B or C)", 123 }, { 124 in: "(A and B) or (A and C) or (A and D)", 125 expected: "A and (B or C or D)", 126 }, { 127 in: "(a=1 or a IN (1,2)) or (a = 2 or a = 3)", 128 expected: "a in (1, 2, 3)", 129 }, { 130 in: "A and (B or A)", 131 expected: "A", 132 }} 133 134 for _, tc := range tests { 135 in.Run(tc.in, func(t *testing.T) { 136 expr, err := ParseExpr(tc.in) 137 require.NoError(t, err) 138 139 output := RewritePredicate(expr) 140 assert.Equal(t, tc.expected, String(output)) 141 }) 142 } 143 } 144 145 func TestExtractINFromOR(in *testing.T) { 146 tests := []struct { 147 in string 148 expected string 149 }{{ 150 in: "(A and B) or (B and A)", 151 expected: "<nil>", 152 }, { 153 in: "(a = 5 and B) or A", 154 expected: "<nil>", 155 }, { 156 in: "a = 5 and B or a = 6 and C", 157 expected: "a in (5, 6)", 158 }, { 159 in: "(a = 5 and b = 1 or b = 2 and a = 6)", 160 expected: "a in (5, 6) and b in (1, 2)", 161 }, { 162 in: "(a in (1,5) and B or C and a = 6)", 163 expected: "a in (1, 5, 6)", 164 }, { 165 in: "(a in (1, 5) and B or C and a in (5, 7))", 166 expected: "a in (1, 5, 7)", 167 }} 168 169 for _, tc := range tests { 170 in.Run(tc.in, func(t *testing.T) { 171 expr, err := ParseExpr(tc.in) 172 require.NoError(t, err) 173 174 output := ExtractINFromOR(expr.(*OrExpr)) 175 assert.Equal(t, tc.expected, String(AndExpressions(output...))) 176 }) 177 } 178 }