func simplifyNotExpr(n *parser.NotExpr) (parser.TypedExpr, bool) { switch t := n.Expr.(type) { case *parser.ComparisonExpr: op := t.Operator switch op { case parser.EQ: op = parser.NE case parser.NE: op = parser.EQ case parser.GT: op = parser.LE case parser.GE: op = parser.LT case parser.LT: op = parser.GE case parser.LE: op = parser.GT case parser.In: op = parser.NotIn case parser.NotIn: op = parser.In case parser.Like: op = parser.NotLike case parser.NotLike: op = parser.Like case parser.SimilarTo: op = parser.NotSimilarTo case parser.NotSimilarTo: op = parser.SimilarTo default: return parser.MakeDBool(true), false } return simplifyExpr(parser.NewTypedComparisonExpr( op, t.TypedLeft(), t.TypedRight(), )) case *parser.AndExpr: // De Morgan's Law: NOT (a AND b) -> (NOT a) OR (NOT b) return simplifyExpr(parser.NewTypedOrExpr( parser.NewTypedNotExpr(t.TypedLeft()), parser.NewTypedNotExpr(t.TypedRight()), )) case *parser.OrExpr: // De Morgan's Law: NOT (a OR b) -> (NOT a) AND (NOT b) return simplifyExpr(parser.NewTypedAndExpr( parser.NewTypedNotExpr(t.TypedLeft()), parser.NewTypedNotExpr(t.TypedRight()), )) } return parser.MakeDBool(true), false }
func makeNot(expr parser.TypedExpr) parser.TypedExpr { if expr == parser.DBoolTrue { return parser.DBoolFalse } if expr == parser.DBoolFalse { return parser.DBoolTrue } return parser.NewTypedNotExpr(expr) }