Mojo-DB-Results-Role-MoreMethods

 view release on metacpan or  search on metacpan

lib/Mojo/DB/Results/Role/MoreMethods.pm  view on Meta::CPAN


        my $index = $indexes[0] // 0;
        $self->_assert_indexes($index);

        return $array->[$index];
    }
}

sub get_by_name {
    my $self = shift;

    my $options = ref $_[0] eq 'HASH' ? shift : {};
    my @names = @_;
    Carp::croak 'names required' unless @names;

    return $self->get($options, $self->_find_column_indexes(@names));
}

sub c {
    return shift->get(@_) if not defined wantarray;

    my @values = shift->get(@_);
    return @values ? Mojo::Collection->new(@values) : undef;
}

sub c_by_name {
    return shift->get_by_name(@_) if not defined wantarray;

    my @values = shift->get_by_name(@_);
    return @values ? Mojo::Collection->new(@values) : undef;
}

sub collections { Mojo::Collection->new(map { Mojo::Collection->new(@$_) } @{ shift->arrays }) }

sub flatten { shift->arrays->flatten }

sub hashify {
    my $self = shift;
    my ($collection, $get_keys, $get_value) = $self->_parse_transform_options({}, @_);

    return $collection->with_roles('+Transform')->hashify($get_keys, $get_value);
}

sub hashify_collect {
    my ($collection, $get_keys, $get_value, $flatten) = shift->_parse_transform_options({flatten_allowed => 1}, @_);

    return $collection->with_roles('+Transform')->hashify_collect({flatten => $flatten}, $get_keys, $get_value);
}

sub collect_by {
    my ($collection, $get_keys, $get_value, $flatten) = shift->_parse_transform_options({flatten_allowed => 1}, @_);

    return $collection->with_roles('+Transform')->collect_by({flatten => $flatten}, $get_keys, $get_value);
}

sub _parse_transform_options {
    my $self = shift;
    my $private_options = shift;
    my $options = ref $_[0] eq 'HASH' ? shift : {};

    my ($key, $key_ref)                       = _parse_and_validate_transform_key(shift);
    my ($value, $value_is_column, $value_ref) = _parse_and_validate_transform_value(@_);

    my ($type, $flatten) = _parse_and_validate_transform_options($private_options, $options);

    # if user will not access the rows and the type won't be used, default rows to arrays for speed
    if (($value_is_column or $flatten) and $key_ref ne 'CODE' and $value_ref ne 'CODE') {
        if ($type and $type ne 'array') {
            Carp::cluck 'Useless type option provided. array will be used for performance.';
        }
        $type = 'array';
    } elsif (not $type) {
        $type = 'hash';
    }

    my $get_keys   = $key_ref eq 'CODE'   ? $key : $self->_create_get_keys_sub($type, $key);
    my $get_value  = $value_ref eq 'CODE' ? $value
                   : $value_is_column     ? $self->_create_column_value_getter($type, $value)
                   : $flatten             ? $self->_create_flatten_value_getter($type)
                   : sub { $_ }
                   ;
    my $collection = $type eq 'array' ? $self->arrays
                   : $type eq 'c'     ? $self->collections
                   : $type eq 'hash'  ? $self->hashes
                   : $self->structs
                   ;

    return $collection, $get_keys, $get_value, $flatten;
}

sub _parse_and_validate_transform_key {
    my ($key) = @_;

    my $key_ref = ref $key;
    if ($key_ref) {
        Carp::confess qq{key must be an arrayref, a sub or a non-empty string, but had ref '$key_ref'}
            unless $key_ref eq 'ARRAY' or $key_ref eq 'CODE';

        if ($key_ref eq 'ARRAY') {
            Carp::confess 'key array must not be empty' unless @$key;
            Carp::confess 'key array elements must be defined and non-empty' if grep { not defined or $_ eq '' } @$key;
        }
    } else {
        Carp::confess 'key was undefined or an empty string' unless defined $key and $key ne '';
        $key = [$key];
    }

    return $key, $key_ref;
}

sub _parse_and_validate_transform_value {
    my ($value, $value_is_column);

    my $value_ref;
    if (@_ == 1) {
        $value = shift;

        $value_ref = ref $value;
        if ($value_ref) {
            Carp::confess qq{value must be a sub or non-empty string, but was '$value_ref'} unless $value_ref eq 'CODE';
        } elsif (not defined $value or $value eq '') {
            Carp::confess 'value must not be undefined or an empty string';
        } else {
            $value_is_column = 1;
        }
    } elsif (@_ > 1) {
        Carp::confess 'too many arguments provided (more than one value)';
    }

    return $value, $value_is_column, $value_ref // '';
}

sub _parse_and_validate_transform_options {
    my ($private_options, $options) = @_;

    my $flatten;
    if ($private_options->{flatten_allowed}) {
        $flatten = delete $options->{flatten};
    } else {
        Carp::confess 'flatten not allowed' if exists $options->{flatten};
    }

    my $flatten_allowed_text = $private_options->{flatten_allowed} ? 'In addition to flatten, ' : '';
    Carp::confess "${flatten_allowed_text}one key/value pair is allowed for options"
        if keys %$options > 1;

    my $type;
    if (%$options) {
        ($type) = keys %$options;

        my @valid_types = qw(array c hash struct);
        Carp::confess "${flatten_allowed_text}option must be one of: @{[ join ', ', @valid_types ]}"
            unless grep { $type eq $_ } @valid_types;
    }

    return $type, $flatten;
}

sub _create_get_keys_sub {
    my ($self, $type, $key) = @_;

    if ($type eq 'array' or $type eq 'c') {
        my @key_indexes = $self->_find_column_indexes(@$key);
        return sub { @{$_}[@key_indexes] };
    } elsif ($type eq 'hash') {
        # assert columns exist
        $self->_find_column_indexes(@$key);

        return sub { @{$_}{@$key} };
    } else {
        # assert columns exist
        $self->_find_column_indexes(@$key);

        return sub {
            map { $_[0]->${\$_} } @$key
        };
    }
}

sub _create_column_value_getter {
    my ($self, $type, $value) = @_;

    if ($type eq 'array' or $type eq 'c') {
        my $column_index = $self->_find_column_indexes($value);
        return sub { $_->[$column_index] };
    } elsif ($type eq 'hash') {
        # assert that column exists
        $self->_find_column_indexes($value);

        return sub { $_->{$value} };
    } else {
        # assert that column exists
        $self->_find_column_indexes($value);



( run in 1.341 second using v1.01-cache-2.11-cpan-0b5f733616e )