NAME

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

VERSION

Version 0.41

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.

ARCHITECTURAL ROLE

In a standard DBIC environment, the ResultSet holds a live database handle. In the Async environment, the "real" ResultSet lives in a background worker. This class exists on the application side to provide:

Lazy Inflation

Results are not turned into objects until they are actually needed. This saves CPU cycles if you are only passing data through to a JSON encoder.

Relationship Stitching

When search_with_prefetch is used, the worker sends back a nested data structure. This class's new_result method is responsible for "stitching" that data back together so that $user->orders returns the prefetched collection without triggering new database queries.

Dynamic Class Hijacking

This class uses an anonymous proxy pattern to ensure that if a user requests a custom result_class, the resulting objects inherit correctly from both the Async framework and the user's custom class.

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.

new_result

my $row = $rs->new_result($hashref);

A core inflation method that transforms a raw hash of database results into a fully-functional row object. Unlike standard inflation, this method is architected for the asynchronous, disconnected nature of background workers.

Features

  • Dynamic Subclassing:

    Generates a specialised class (e.g., DBIx::Class::Async::Row::User) per ResultSource to ensure clean method resolution.

  • Custom Class Support:

    If a result_class is set, it dynamically creates an anonymous proxy (...::Anon::*) that uses multiple inheritance to combine your custom methods with the asynchronous row logic.

  • Deep Inflation (Prefetch):

    Detects nested data structures (hashes or arrays) in the input and injects them into the object's internal relationship cache, allowing for non-blocking access to related data.

  • Data Normalization:

    Handles SQL aliases (like me.id), primary key detection for storage state, and preserves literal SQL columns (like COUNT(*)) that may not exist in the schema.

Returns a blessed object inheriting from DBIx::Class::Async::Row. Returns undef if the provided data is empty or undefined.

new_result_set

my $new_rs = $rs->new_result_set({
    entries       => \@prefetched_data,
    is_prefetched => 0
});

Creates a new instance (clone) of the current ResultSet class, inheriting the schema, database connection, and source name.

This is primarily used internally to handle prefetched relationships. When a has_many relationship is accessed, this method creates a "virtual" ResultSet seeded with the data already retrieved in the initial query, preventing unnecessary follow-up database hits.

Accepts a hashref of attributes to override in the new instance.

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, with prefetched relationships properly inflated.

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.

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.

clear_cache

$rs->clear_cache;

Clears the internal cache of the ResultSet. This forces the next execution of the ResultSet to fetch fresh data from the database (or the global query cache). Returns undef.

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.

count_literal

my $count = await $rs->count_literal('age > ? AND status = ?', 18, 'active');
Arguments: $sql_fragment, @standalone_bind_values
Return Value: Future (resolving to Integer)

Counts the results in a literal query.

This method is provided primarily for Class::DBI compatibility. It is equivalent to calling "search_literal" with the passed arguments, followed by "count".

Because this triggers an immediate database query, it returns a Future that will resolve to the integer count once the worker process has completed the execution.

Note: Always use placeholders (?) in your $sql_fragment to maintain security and prevent SQL injection.

count_rs

my $count_rs = $rs->count_rs({ active => 1 });
# Use as a subquery:
my $users = await $schema->resultset('User')->search({
    login_count => $count_rs->as_query
})->all;
Arguments: $cond?, \%attrs?
Return Value: DBIx::Class::Async::ResultSet

Returns a new ResultSet object that, when executed, performs a COUNT(*) operation. Unlike count, this method is lazy and does not dispatch a request to the worker pool immediately. It is primarily useful for constructing subqueries or complex joins where the count is part of a larger query.

count_total

my $future = $rs->count_total;
my $total  = $future->get;

Returns a Future that resolves to the total number of records matching the ResultSet's conditions, specifically ignoring any pagination attributes (rows, offset, or page).

This is distinct from the standard count method, which in an asynchronous context often reflects the size of the current page (the "slice") rather than the total dataset. This method is used internally by the pager to calculate the last page number and total entries.

You can optionally pass additional conditions or attributes to be merged:

my $total = $rs->count_total({ status => 'active' })->get;

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.

cursor

my $cursor = $rs->cursor;

Returns a DBIx::Class::Async::Storage::DBI::Cursor object for iterating through the ResultSet's rows asynchronously.

The cursor provides a low-level interface for fetching rows one at a time using Futures, which is useful for processing large result sets without loading all rows into memory at once.

use Future::AsyncAwait;

my $rs = $schema->resultset('User');
my $cursor = $rs->cursor;

my $iter = async sub {
    while (my $row = await $cursor->next) {
        # Process each row asynchronously
        say $row->name;
    }
};

$iter->get;  # Wait for iteration to complete

The cursor respects the ResultSet's rows attribute for batch fetching:

my $rs = $schema->resultset('User')->search(undef, { rows => 50 });
my $cursor = $rs->cursor;  # Will fetch 50 rows at a time

See DBIx::Class::Async::Storage::DBI::Cursor for available cursor methods including next() and reset().

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.

delete_all

$rs->delete_all->then(sub {
    my ($deleted_count) = @_;
    say "Deleted $deleted_count rows";
});

Fetches all objects and deletes them one at a time via "delete" in DBIx::Class::Row.

Arguments

None

Returns

A Future that resolves to the number of rows deleted.

Difference from delete()

delete_all will run DBIC-defined triggers (such as before_delete, after_delete), and will handle cascading deletes through relationships, while delete() performs a more efficient bulk delete that bypasses Row-level operations.

Use delete_all when you need: - Row-level triggers to fire - Cascading deletes to work properly - Accurate counts of rows affected

Use delete when you need: - Better performance for large datasets - Direct database-level deletion

Example
# Delete with triggers
$rs->search({ expired => 1 })->delete_all->then(sub {
    my ($count) = @_;
    say "Deleted $count expired records with triggers";
});

# Compare with bulk delete (no triggers)
$rs->search({ expired => 1 })->delete->then(sub {
    my ($count) = @_;
    say "Bulk deleted $count records (no triggers)";
});

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.

find_or_new

my $future = $rs->find_or_new({ name => 'Alice' }, { key => 'user_name' });

$future->on_done(sub {
    my $user = shift;
    $user->insert if !$user->in_storage;
});

Finds a record using find. If no row is found, it returns a new Result object inflated with the provided data. This object is not yet saved to the database.

find_or_create

my $future = $rs->find_or_create({ name => 'Bob' });

Attempts to find a record. If it does not exist, it performs an INSERT and returns the resulting Result object.

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.

first_future

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

Alias for single_future.

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_cache

my $cached_rows = $rs->get_cache;

Returns the current contents of the ResultSet's internal cache. This will be an arrayref of DBIx::Class::Async::Row objects if the cache has been populated via set_cache or a previous execution of all. Returns undef if no cache exists.

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.

is_paged

if ($rs->is_paged) { ... }

Returns a boolean (1 or 0) indicating whether the ResultSet has pagination attributes (specifically the page key) defined.

is_ordered

my $bool = $rs->is_ordered;

Returns true (1) if the ResultSet has an order_by attribute set, false (0) otherwise. It is highly recommended to ensure a ResultSet is_ordered before performing pagination to ensure consistent results across pages.

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.

page

my $paged_rs = $rs->page(3);

Returns a new ResultSet clone with the page and rows attributes set. If rows (entries per page) has not been previously set on the ResultSet, it defaults to 10.

This method is chainable and does not execute a query immediately.

pager

my $pager = $rs->page(1)->pager;

Returns a DBIx::Class::Async::ResultSet::Pager object for the current ResultSet. This object provides methods to calculate the total number of pages, next/previous page numbers, and entry counts.

Note: This method will die if called on a ResultSet that has not been paged via the "page" method.

PRO-TIP: Warn the user if they are paginating unordered data.

populate

# Array of hashrefs format
$rs->populate([
    { name => 'Alice', email => 'alice@example.com' },
    { name => 'Bob',   email => 'bob@example.com' },
])->then(sub {
    my ($users) = @_;
    say "Created " . scalar(@$users) . " users";
});

# Column list + rows format
$rs->populate([
    [qw/ name email /],
    ['Alice', 'alice@example.com'],
    ['Bob',   'bob@example.com'],
])->then(sub {
    my ($users) = @_;
});

Creates multiple rows at once. More efficient than calling create multiple times.

Arguments
$data

Either:

- Array of hashrefs: [ \%col_data, \%col_data, ... ]

- Column list + rows: [ \@column_list, \@row_values, \@row_values, ... ]

Returns

A Future that resolves to an arrayref of created DBIx::Class::Async::Row objects.

populate_bulk

my $future = $rs->populate_bulk(\@large_dataset);

$future->on_done(sub {
    print "Bulk insert successful\n";
});

A high-performance version of populate intended for large-scale data ingestion.

  • Arguments: [ \%col_data, ... ] or [ \@column_list, [ \@row_values, ... ] ]

  • Return Value: A Future that resolves to a truthy value (1) on success.

Key Differences from populate:

1. Context: Executes the database operation in void context on the worker side.
2. No Inflation: Does not create Result objects for the inserted rows.
3. Efficiency: Reduces memory overhead and Inter-Process Communication (IPC) payload by only returning a success status rather than the full row data.

Use this method when you need to "fire and forget" large amounts of data where individual object manipulation is not required immediately after insertion.

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.

my $users_rs = $orders_rs->related_resultset('user');

Returns a new ResultSet for a related table based on a relationship name. The new ResultSet will be constrained to only include records that are related to records in the current ResultSet.

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).

result_class

$rs->result_class('My::Custom::Row::Class');
my $class = $rs->result_class;

Gets or sets the result class (inflation class) for the ResultSet.

In DBIx::Class::Async, this method plays a critical role in maintaining Object-Oriented compatibility. When a custom result class is specified, the library automatically generates an anonymous proxy class that inherits from both the internal asynchronous logic and your custom class.

This ensures that:

1. Custom row methods (e.g., hello_name) are available on returned objects.
2. The objects correctly pass $row->isa('My::Custom::Row::Class') checks.
3. Database interactions remain asynchronous and non-blocking.

The method resolves the class using the following priority:

1. Explicitly set value via this accessor.
2. Attributes passed during the search call (result_class).
3. The default result_class defined in the DBIx::Class::ResultSource.

Returns the ResultSet object when used as a setter to allow method chaining.

result_source

my $source = $rs->result_source;

Returns the result source object for this result set.

Returns

A DBIx::Class::ResultSource object.

schema

my $schema = $rs->schema;

Returns the DBIx::Class::Async::Schema object that this ResultSet belongs to.

This provides access to the parent schema, allowing you to access other ResultSources, the storage layer, or schema-level operations from within a ResultSet context.

my $rs = $schema->resultset('User');
my $parent_schema = $rs->schema;

# Access other result sources
my $orders_rs = $parent_schema->resultset('Order');

# Access storage
my $storage = $parent_schema->storage;

# Perform schema-level operations
$parent_schema->txn_do(sub { ... });

This method is particularly useful in ResultSet method chains or custom ResultSet classes where you need to access the schema without passing it as a parameter.

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.

search_future

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

Alias for all_future.

search_literal

my $rs = $schema->resultset('User')->search_literal(
    'age > ? AND status = ?',
    18, 'active'
);
Arguments: $sql_fragment, @bind_values
Return Value: DBIx::Class::Async::ResultSet

Performs a search using a literal SQL fragment. This is provided for compatibility with Class::DBI.

Warning: Use this method with caution. Always use placeholders (?) for values to prevent SQL injection. Literal fragments are not parsed or validated by the ORM before being sent to the database.

# Scalar context: returns a ResultSet
my $new_rs = $rs->search_related('orders');

# List context: returns a Future (implicit ->all)
my $future = $rs->search_related('orders');
my @orders = $future->get;

In scalar context, works exactly like "search_related_rs". In list context, it returns a Future that resolves to the list of objects in that relationship.

my $rel_rs = $rs->search_related_rs('relationship_name', \%cond?, \%attrs?);

Returns a new DBIx::Class::Async::ResultSet representing the specified relationship. This is a synchronous metadata operation and does not hit the database.

search_with_pager

my $future = $rs->search_with_pager({ status => 'active' }, { rows => 20 });

$future->then(sub {
    my ($rows, $pager) = @_;
    print "Displaying page " . $pager->current_page;
    return Future->done;
})->get;

This is a convenience method that performs a search and initializes a pager simultaneously. It returns a Future which, when resolved, provides two values: an arrayref of result objects ($rows) and a DBIx::Class::Async::ResultSet::Pager object ($pager).

Performance Note

Unlike standard synchronous pagination where you must first fetch the data and then fetch the count (or vice versa), search_with_pager fires both the SELECT and the COUNT queries to the database worker pool in parallel using "needs_all" in Future. This can significantly reduce latency in web applications.

If the ResultSet is not already paged when this method is called, it automatically applies ->page(1).

set_cache

$rs->set_cache(\@row_objects);

Manually populates the ResultSet cache with the provided arrayref of row objects. Once a cache is set, any subsequent data-fetching operations (like all or single_future) will return the cached objects immediately instead of querying the database or the global worker cache.

Expects an arrayref of objects of the same class as those normally produced by the ResultSet.

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.

slice

my ($first, $second, $third) = $rs->slice(0, 2);
my @records = $rs->slice(5, 10);
my $sliced_rs = $rs->slice(0, 9);  # scalar context

Returns a resultset or object list representing a subset of elements from the resultset. Indexes are from 0.

Parameters
$first

Zero-based starting index (inclusive).

$last

Zero-based ending index (inclusive).

Returns

In list context: Array of DBIx::Class::Async::Row objects.

In scalar context: A new DBIx::Class::Async::ResultSet with appropriate rows and offset attributes set.

Examples
# Get first 3 records
my ($one, $two, $three) = $rs->slice(0, 2);

# Get records 10-19
my @batch = $rs->slice(10, 19);

# Get a ResultSet for records 5-14 (for further chaining)
my $subset_rs = $rs->slice(5, 14);
my $count = $subset_rs->count->get;

source

my $source = $rs->source;

Alias for result_source.

Returns

A DBIx::Class::ResultSource object.

sub source { shift->_get_source }

source_name

my $source_name = $rs->source_name;

Returns the source name for this result set.

Returns

The source name (string).

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.

update_or_create

my $future = $rs->update_or_create({
     email => 'user@example.com',
     name  => 'Updated Name',
    active => 1
}, { key => 'user_email' });

$future->on_done(sub {
    my $row = shift;
    print "Upserted user ID: " . $row->id;
});

An "upsert" operation. It first attempts to locate an existing record using the unique constraints provided in the data hashref (or specified by the key attribute).

  • If a matching record is found, it is updated with the remaining values in the hashref.

  • If no matching record is found, a new record is inserted into the database.

Returns a Future which, when resolved, provides the DBIx::Class::Async::Row object representing the updated or newly created record.

update_or_new

my $future = $rs->update_or_new({
     email => 'user@example.com',
     name  => 'New Name'
}, { key => 'user_email' });

Similar to "update_or_create", but with a focus on in-memory instantiation.

  • If a matching record is found in the database, it is updated and the resulting object is returned.

  • If no record is found, a new row object is instantiated (using "new_result") but not yet saved to the database.

This is useful for workflows where you want to ensure an object is synchronised with the database if it exists, but you aren't yet ready to commit a new record to storage.

Returns a Future resolving to a DBIx::Class::Async::Row 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.

CACHING METHODS

These methods allow for manual management of the ResultSet's internal data cache. Note that this is separate from the global query cache managed by the DBIx::Class::Async object.

get_cache
set_cache
clear_cache

INTERNAL METHODS

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

my $new_async_rs = $rs->_do_search_related($rel_name, $cond, $attrs);

An internal helper method that performs the heavy lifting for "search_related" and "search_related_rs".

NOTE: This method exists to break deep recursion issues caused by DBIx::Class method aliasing. It bypasses the standard method dispatcher by manually instantiating a native DBIx::Class::ResultSet to calculate relationship metadata before re-wrapping the result in the Async class.

_get_source

my $source = $rs->_get_source;

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

_inflate_prefetch

Inflates prefetched relationship data into the row object.

_inflate_simple_prefetch

Inflates a simple (non-nested) prefetched relationship.

_inflate_nested_prefetch

Inflates nested prefetched relationships (e.g., 'comments.user').

_find_reverse_relationship

Finds the reverse relationship name on the related source.

_resolved_attrs

my $attrs = $rs->_resolved_attrs;
my $rows  = $attrs->{rows};
Return Value: HashRef

An internal helper method that returns the raw attributes hash for the current ResultSet. This includes things like order_by, join, prefetch, rows, and offset.

If no attributes have been set, it returns an empty anonymous hash reference ({}) to ensure that calls to specific keys (e.g., $rs-_resolved_attrs->{rows}>) do not trigger "not a HASH reference" errors.

Note: This is intended for internal use and testing. To modify attributes, use the "search" method to create a new ResultSet.

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.