NAME

DBIx::Class::Async::ResultSet - Asynchronous ResultSet for DBIx::Class::Async

VERSION

Version 0.03

SYNOPSIS

use DBIx::Class::Async::ResultSet;

# Typically obtained from DBIx::Class::Async::Schema
my $rs = $schema->resultset('User');

# Synchronous methods (return Future objects)
$rs->all->then(sub {
    my ($users) = @_;
    foreach my $user (@$users) {
        say "User: " . $user->name;
    }
});

$rs->search({ active => 1 })->count->then(sub {
    my ($count) = @_;
    say "Active users: $count";
});

# Asynchronous future methods
$rs->all_future->then(sub {
    my ($data) = @_;
    # Raw data arrayref
});

# Chaining methods
$rs->search({ status => 'active' })
   ->order_by('created_at')
   ->rows(10)
   ->all->then(sub {
       my ($active_users) = @_;
       # Process results
   });

# Create new records
$rs->create({
    name  => 'Alice',
    email => 'alice@example.com',
})->then(sub {
    my ($new_user) = @_;
    say "Created user ID: " . $new_user->id;
});

DESCRIPTION

DBIx::Class::Async::ResultSet provides an asynchronous result set interface for DBIx::Class::Async. It mimics the DBIx::Class::ResultSet API but returns Future objects for database operations, allowing non-blocking asynchronous database access.

This class supports both synchronous-style iteration (using next and reset) and asynchronous operations (using then callbacks). All database operations are delegated to the underlying DBIx::Class::Async instance.

CONSTRUCTOR

new

my $rs = DBIx::Class::Async::ResultSet->new(
    schema      => $schema,            # DBIx::Class::Schema instance
    async_db    => $async_db,          # DBIx::Class::Async instance
    source_name => $source_name,       # Result source name
);

Creates a new asynchronous result set.

Parameters
schema

A DBIx::Class::Schema instance. Required.

async_db

A DBIx::Class::Async instance. Required.

source_name

The name of the result source (table). Required.

Throws
  • Croaks if any required parameter is missing.

METHODS

all

$rs->all->then(sub {
    my ($rows) = @_;
    # $rows is an arrayref of DBIx::Class::Async::Row objects
});

Returns all rows matching the current search criteria as DBIx::Class::Async::Row objects.

Returns

A Future that resolves to an array reference of DBIx::Class::Async::Row objects.

Notes

Results are cached internally for use with next and reset methods.

all_future

$rs->all_future->then(sub {
    my ($data) = @_;
    # $data is an arrayref of raw hashrefs
});

Returns all rows matching the current search criteria as raw data.

Returns

A Future that resolves to an array reference of hash references containing raw row data.

Notes

This method bypasses row object creation for performance. Use all if you need DBIx::Class::Async::Row objects.

count

$rs->count->then(sub {
    my ($count) = @_;
    say "Found $count rows";
});

Returns the count of rows matching the current search criteria.

Returns

A Future that resolves to the number of matching rows.

count_future

$rs->count_future->then(sub {
    my ($count) = @_;
    # Same as count(), alias for API consistency
});

Alias for count. Returns the count of rows matching the current search criteria.

Returns

A Future that resolves to the number of matching rows.

create

$rs->create({ name => 'Alice', email => 'alice@example.com' })
   ->then(sub {
       my ($new_row) = @_;
       say "Created row ID: " . $new_row->id;
   });

Creates a new row in the database.

Parameters
$data

Hash reference containing column-value pairs for the new row.

Returns

A Future that resolves to a DBIx::Class::Async::Row object representing the newly created row.

delete

$rs->search({ status => 'inactive' })->delete->then(sub {
    my ($deleted_count) = @_;
    say "Deleted $deleted_count rows";
});

Deletes all rows matching the current search criteria.

Returns

A Future that resolves to the number of rows deleted.

Notes

This method fetches all matching rows first to count them and get their IDs, then deletes them individually. For large result sets, consider using a direct SQL delete via the underlying database handle.

find

$rs->find($id)->then(sub {
    my ($row) = @_;
    if ($row) {
        say "Found: " . $row->name;
    } else {
        say "Not found";
    }
});

Finds a single row by primary key.

Parameters
$id

Primary key value, or hash reference for composite primary key lookup.

Returns

A Future that resolves to a DBIx::Class::Async::Row object if found, or undef if not found.

Throws
  • Dies if composite primary key is not supported.

first

$rs->first->then(sub {
    my ($row) = @_;
    if ($row) {
        say "First row: " . $row->name;
    }
});

Returns the first row matching the current search criteria.

Returns

A Future that resolves to a DBIx::Class::Async::Row object if found, or undef if no rows match.

get

my $rows = $rs->get;
# Returns cached rows, or empty arrayref if not fetched

Returns the currently cached rows.

Returns

Array reference of cached rows (either raw data or row objects, depending on how they were fetched).

Notes

This method returns immediately without performing any database operations. It only returns data that has already been fetched via all, all_future, or similar methods.

get_column

$rs->get_column('name')->then(sub {
    my ($names) = @_;
    # $names is an arrayref of name values
});

Returns values from a single column for all rows matching the current criteria.

Parameters
$column

Column name to retrieve values from.

Returns

A Future that resolves to an array reference of column values.

next

while (my $row = $rs->next) {
    say "Row: " . $row->name;
}

Returns the next row from the cached result set.

Returns

A DBIx::Class::Async::Row object, or undef when no more rows are available.

Notes

If no rows have been fetched yet, this method performs a blocking fetch via all. The results are cached for subsequent next calls. Call reset to restart iteration.

prefetch

my $rs_with_prefetch = $rs->prefetch('related_table');

Adds a prefetch clause to the result set for eager loading of related data.

Parameters
$prefetch

Prefetch specification (string or arrayref).

Returns

A new result set object with the prefetch clause added.

Notes

This method returns a clone of the result set and does not modify the original.

reset

$rs->reset;
# Now $rs->next will start from the first row again

Resets the internal iterator position.

Returns

The result set object itself (for chaining).

my $filtered_rs = $rs->search({ active => 1 }, { order_by => 'name' });

Adds search conditions and attributes to the result set.

Parameters
$cond

Hash reference of search conditions (optional).

$attrs

Hash reference of search attributes like order_by, rows, etc. (optional).

Returns

A new result set object with the combined conditions and attributes.

Notes

This method returns a clone of the result set. Conditions and attributes are merged with any existing ones from the original result set.

single

my $row = $rs->single;
# Returns first row (blocking), or undef

Returns the first row from the result set (blocking version).

Returns

A DBIx::Class::Async::Row object, or undef if no rows match.

Notes

This method performs a blocking fetch. For non-blocking operation, use first or single_future.

single_future

$rs->single_future->then(sub {
    my ($row) = @_;
    if ($row) {
        # Process single row
    }
});

Returns a single row matching the current search criteria (non-blocking).

Returns

A Future that resolves to a DBIx::Class::Async::Row object if found, or undef if not found.

Notes

For simple primary key lookups, this method optimizes by using find internally. For complex queries, it adds rows => 1 to the search attributes.

update

$rs->search({ status => 'pending' })->update({ status => 'processed' })
   ->then(sub {
       my ($rows_affected) = @_;
       say "Updated $rows_affected rows";
   });

Updates all rows matching the current search criteria.

Parameters
$data

Hash reference containing column-value pairs to update.

Returns

A Future that resolves to the number of rows affected.

Notes

This performs a bulk update using the search conditions. For individual row updates, use update on the row object instead.

as_query

my ($cond, $attrs) = $rs->as_query;

Returns the internal search conditions and attributes.

Returns

A list containing two hash references: conditions and attributes.

result_source

my $source = $rs->result_source;

Returns the result source object for this result set.

Returns

A DBIx::Class::ResultSource object.

source

my $source_name = $rs->source_name;

Returns the source name for this result set.

Returns

The source name (string).

source

my $source = $rs->source;

Alias for result_source.

Returns

A DBIx::Class::ResultSource object.

CHAINABLE MODIFIERS

The following methods return a new result set with the specified attribute added or modified:

rows($number) - Limits the number of rows returned
page($number) - Specifies the page number for pagination
order_by($spec) - Specifies the sort order
columns($spec) - Specifies which columns to select
group_by($spec) - Specifies GROUP BY clause
having($spec) - Specifies HAVING clause
distinct($bool) - Specifies DISTINCT modifier

Example:

my $paginated = $rs->rows(10)->page(2)->order_by('created_at DESC');

These methods do not modify the original result set and do not execute any database queries.

INTERNAL METHODS

These methods are for internal use and are documented for completeness.

_get_source

my $source = $rs->_get_source;

Returns the result source object, loading it lazily if needed.

search_future

$rs->search_future->then(sub {
    # Same as all_future, alias for API consistency
});

Alias for all_future.

first_future

$rs->first_future->then(sub {
    # Same as single_future, alias for API consistency
});

Alias for single_future.

SEE ALSO

AUTHOR

Mohammad Sajid Anwar, <mohammad.anwar at yahoo.com>

REPOSITORY

https://github.com/manwar/DBIx-Class-Async

BUGS

Please report any bugs or feature requests through the web interface at https://github.com/manwar/DBIx-Class-Async/issues. I will be notified and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc DBIx::Class::Async::ResultSet

You can also look for information at:

LICENSE AND COPYRIGHT

Copyright (C) 2026 Mohammad Sajid Anwar.

This program is free software; you can redistribute it and / or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License.By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you,you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement,then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.