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  }