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_prefetchis used, the worker sends back a nested data structure. This class'snew_resultmethod is responsible for "stitching" that data back together so that$user->ordersreturns 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_classis 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 (likeCOUNT(*)) 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
nextandresetmethods.
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
allif 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
- 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_allwill run DBIC-defined triggers (such asbefore_delete,after_delete), and will handle cascading deletes through relationships, whiledelete()performs a more efficient bulk delete that bypasses Row-level operations.Use
delete_allwhen you need: - Row-level triggers to fire - Cascading deletes to work properly - Accurate counts of rows affectedUse
deletewhen 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
- Returns
-
A Future that resolves to a DBIx::Class::Async::Row object if found, or
undefif 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
undefif 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
- 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
undefwhen 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 subsequentnextcalls. Callresetto 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
- 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
- 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.
related_resultset
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
searchcall (result_class). - 3. The default
result_classdefined 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.
search
my $filtered_rs = $rs->search({ active => 1 }, { order_by => 'name' });
Adds search conditions and attributes to the result set.
- Parameters
- 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.
search_related
# 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.
search_related_rs
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
undefif no rows match. - Notes
-
This method performs a blocking fetch. For non-blocking operation, use
firstorsingle_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
undefif not found. - Notes
-
For simple primary key lookups, this method optimizes by using
findinternally. For complex queries, it addsrows => 1to 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
- Returns
-
In list context: Array of DBIx::Class::Async::Row objects.
In scalar context: A new DBIx::Class::Async::ResultSet with appropriate
rowsandoffsetattributes 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
- 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
updateon 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 returnedpage($number)- Specifies the page number for paginationorder_by($spec)- Specifies the sort ordercolumns($spec)- Specifies which columns to selectgroup_by($spec)- Specifies GROUP BY clausehaving($spec)- Specifies HAVING clausedistinct($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.
_do_search_related
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.
Arguments: Same as "search_related_rs".
Returns: A new DBIx::Class::Async::ResultSet object.
_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};
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
DBIx::Class::Async - Asynchronous DBIx::Class interface
DBIx::Class::ResultSet - Synchronous DBIx::Class result set interface
DBIx::Class::Async::Row - Asynchronous row objects
Future - Asynchronous programming abstraction
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:
BUG Report
CPAN Ratings
Search MetaCPAN
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.