stripFuncResultTextCasts removes text/character varying casts applied to function call results, e.g. current_setting(...)::text -> current_setting(...). PostgreSQL drops such casts when they are no-ops while storing policy expressions, so they must be ignored when comparing policies. This is only sa
(expr parser.Expr)
| 606 | // safe for comparison; do not use the result to generate DDLs because casts on |
| 607 | // functions returning non-text types are semantically meaningful. |
| 608 | func stripFuncResultTextCasts(expr parser.Expr) parser.Expr { |
| 609 | if expr == nil { |
| 610 | return nil |
| 611 | } |
| 612 | |
| 613 | switch e := expr.(type) { |
| 614 | case *parser.CastExpr: |
| 615 | inner := e.Expr |
| 616 | if paren, ok := inner.(*parser.ParenExpr); ok { |
| 617 | inner = paren.Expr |
| 618 | } |
| 619 | if _, isFunc := inner.(*parser.FuncExpr); isFunc && e.Type != nil { |
| 620 | typeStr := strings.ToLower(e.Type.Type) |
| 621 | if typeStr == "text" || typeStr == "character varying" { |
| 622 | return stripFuncResultTextCasts(inner) |
| 623 | } |
| 624 | } |
| 625 | return &parser.CastExpr{Expr: stripFuncResultTextCasts(e.Expr), Type: e.Type} |
| 626 | case *parser.ParenExpr: |
| 627 | return &parser.ParenExpr{Expr: stripFuncResultTextCasts(e.Expr)} |
| 628 | case *parser.NotExpr: |
| 629 | return &parser.NotExpr{Expr: stripFuncResultTextCasts(e.Expr)} |
| 630 | case *parser.AndExpr: |
| 631 | return &parser.AndExpr{Left: stripFuncResultTextCasts(e.Left), Right: stripFuncResultTextCasts(e.Right)} |
| 632 | case *parser.OrExpr: |
| 633 | return &parser.OrExpr{Left: stripFuncResultTextCasts(e.Left), Right: stripFuncResultTextCasts(e.Right)} |
| 634 | case *parser.ConcatExpr: |
| 635 | return &parser.ConcatExpr{Left: stripFuncResultTextCasts(e.Left), Right: stripFuncResultTextCasts(e.Right)} |
| 636 | case *parser.ComparisonExpr: |
| 637 | return &parser.ComparisonExpr{ |
| 638 | Operator: e.Operator, |
| 639 | Left: stripFuncResultTextCasts(e.Left), |
| 640 | Right: stripFuncResultTextCasts(e.Right), |
| 641 | Escape: stripFuncResultTextCasts(e.Escape), |
| 642 | All: e.All, |
| 643 | Any: e.Any, |
| 644 | } |
| 645 | case *parser.BinaryExpr: |
| 646 | return &parser.BinaryExpr{ |
| 647 | Operator: e.Operator, |
| 648 | Left: stripFuncResultTextCasts(e.Left), |
| 649 | Right: stripFuncResultTextCasts(e.Right), |
| 650 | } |
| 651 | case *parser.RangeCond: |
| 652 | return &parser.RangeCond{ |
| 653 | Operator: e.Operator, |
| 654 | Left: stripFuncResultTextCasts(e.Left), |
| 655 | From: stripFuncResultTextCasts(e.From), |
| 656 | To: stripFuncResultTextCasts(e.To), |
| 657 | } |
| 658 | case *parser.IsExpr: |
| 659 | return &parser.IsExpr{Operator: e.Operator, Expr: stripFuncResultTextCasts(e.Expr)} |
| 660 | case *parser.FuncExpr: |
| 661 | exprs := make(parser.SelectExprs, len(e.Exprs)) |
| 662 | for i, arg := range e.Exprs { |
| 663 | if aliased, ok := arg.(*parser.AliasedExpr); ok { |
| 664 | exprs[i] = &parser.AliasedExpr{Expr: stripFuncResultTextCasts(aliased.Expr), As: aliased.As} |
| 665 | } else { |
no outgoing calls