RaCoCo result: Red::ColumnMethods

# Red::ColumnMethods 46.2%

    use Red::AST::Unary;
    use Red::AST::Infixes;
    use Red::AST::Value;
    use Red::AST::StringFuncs;
    use Red::AST::DateTimeFuncs;
    use Red::AST::JsonItem;
    use Red::AST::JsonRemoveItem;
    use Red::Type::Json;

    =head2 Red::ColumnMethods

    #| Red::Column methods
    unit role Red::ColumnMethods;

    #| Tests if that column value starts with a specific sub-string
    #| is usually translated for SQL as `column like 'substr%'`
    multi method starts-with(Str() $text is readonly) {
        Red::AST::Like.new(self, ast-value "{ $text }%") but Red::ColumnMethods
    }

    multi method starts-with(Str() $text is rw) {
        Red::AST::Like.new(self, ast-value("{ $text }%"), :bind-left) but Red::ColumnMethods
    }

    #| Tests if that column value ends with a specific sub-string
    #| is usually translated for SQL as `column like '%substr'`
    multi method ends-with(Str() $text is readonly) {
        Red::AST::Like.new(self, ast-value "%{ $text }") but Red::ColumnMethods
    }

    multi method ends-with(Str() $text is rw) {
        Red::AST::Like.new(self, ast-value("%{ $text }"), :bind-left) but Red::ColumnMethods
    }

    #| Tests if that column value contains a specific sub-string
    #| is usually translated for SQL as `column like %'substr%'`
    multi method contains(Str() $text is readonly) {
        Red::AST::Like.new(self, ast-value "%{ $text }%") but Red::ColumnMethods
    }

    multi method contains(Str() $text is rw) {
        Red::AST::Like.new(self, ast-value("%{ $text }%"), :bind-left) but Red::ColumnMethods
    }

    #| Return a substring of the column value
    method substr($base where { .returns ~~ Str }: Int() $offset = 0, Int() $size?) {
        Red::AST::Substring.new(:$base, :$offset, |(:$size with $size)) but Red::ColumnMethods
    }

    #| Return the year from the date column
    method year($base where { .returns ~~ (Date|DateTime|Instant) }:) {
        Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::year)) but Red::ColumnMethods
    }

    #| Return the month from the date column
    method month($base where { .returns ~~ (Date|DateTime|Instant) }:) {
        Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::month)) but Red::ColumnMethods
    }

    #| Return the day from the date column
    method day($base where { .returns ~~ (Date|DateTime|Instant) }:) {
        Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::day)) but Red::ColumnMethods
    }

    #| Return the date from a datetime, timestamp etc
    method yyyy-mm-dd($base where { .returns ~~ (Date|DateTime|Instant) }:) {
         Red::AST::DateTimeCoerce.new(:$base) but Red::ColumnMethods
    }

    method now   { self.attr.type.now   }
    method today { self.attr.type.today }

    #| Return a value from a json hash key
    multi method AT-KEY(\SELF where { .returns ~~ Json }: $key where { $_ ~~ Str or ( $_ ~~ Red::AST and .returns ~~ Str )}) is rw {
        my $obj = Red::AST::JsonItem.new(SELF, ast-value $key);
        Proxy.new:
                FETCH => -> $ { $obj but Red::ColumnMethods },
                STORE => -> $, $value {
                    my $val = do given $value {
                        when Red::AST { $_ }
                        default {
                            my &deflator = Json.deflator;
                            ast-value :type(Json), .&deflator;
                        }
                    }
                    @*UPDATE.push: Pair.new: $obj, $val;
                    $obj but Red::ColumnMethods
                }
    }

    #| Delete and return a value from a json hash key
    multi method DELETE-KEY(\SELF where { .returns ~~ Json }: $key where { $_ ~~ Str or ( $_ ~~ Red::AST and .returns ~~ Str )}) {
        my $obj = Red::AST::JsonItem.new(SELF, ast-value $key);
        @*UPDATE.push: Pair.new: SELF, Red::AST::JsonRemoveItem.new: SELF, ast-value $key;
        $obj
    }

    #| Returns a value from a json array index
    method AT-POS(\SELF where { .returns ~~ Json }: $key where { $_ ~~ Int or ( $_ ~~ Red::AST and .returns ~~ Int )}) is rw {
        my $obj = Red::AST::JsonItem.new(SELF, ast-value $key);
        Proxy.new:
                FETCH => -> $ { $obj but Red::ColumnMethods },
                STORE => -> $, $value {
                    my $val = do given $value {
                        when Red::AST { $_ }
                        default {
                            my &deflator = Json.deflator;
                            ast-value .&deflator, :type(Json)
                        }
                    }
                    @*UPDATE.push: Pair.new: $obj, $val;
                    $obj but Red::ColumnMethods
                }
    }