NAME
DBIx::EAV::ResultSet - Represents a query used for fetching a set of entities.
SYNOPSIS
# resultsets are bound to an entity type
my $cds_rs = $eav->resultset('CD');
# insert CDs
my $cd1 = $cds_rs->insert({ title => 'CD1', tracks => \@tracks });
my $cd2 = $cds_rs->insert({ title => 'CD2', tracks => \@tracks });
my $cd3 = $cds_rs->insert({ title => 'CD3', tracks => \@tracks });
# ... or use populate() to insert many
my (@cds) = $cds_rs->populate(\@cds);
# find all 2015 cds
my @cds = $eav->resultset('CD')->search({ year => 2015 });
foreach my $cd (@cds) {
printf "CD '%s' has %d tracks.\n",
$cd->get('title'),
$cd->get('tracks')->count;
}
# find one
my $cd2 = $cds_rs->search_one({ name => 'CD2' });
# find by related attribute
my $cd2 = $cds_rs->search_one({ 'tracks.title' => 'Some CD2 Track' });
# count
my $top_cds_count = $cds_rs->search({ rating => { '>' => 7 } })->count;
# update
# delete all entities
$cds_rs->delete; # fast, but doesn't deletes related entities
$cds_rs->delete_all; # cascade delete all cds and related entities
DESCRIPTION
A ResultSet is an object which stores a set of conditions representing a query. It is the backbone of DBIx::EAV (i.e. the really important/useful bit).
No SQL is executed on the database when a ResultSet is created, it just stores all the conditions needed to create the query.
A basic ResultSet representing the data of an entire table is returned by calling resultset
on a DBIx::EAV and passing in a type name.
my $users_rs = $eav->resultset('User');
A new ResultSet is returned from calling "search" on an existing ResultSet. The new one will contain all the conditions of the original, plus any new conditions added in the search
call.
A ResultSet also incorporates an implicit iterator. "next" and "reset" can be used to walk through all the entities the ResultSet represents.
The query that the ResultSet represents is only executed against the database when these methods are called: "find", "next", "all", "first", "count".
If a resultset is used in a numeric context it returns the "count". However, if it is used in a boolean context it is always true. So if you want to check if a resultset has any results, you must use if $rs != 0
.
METHODS
new_entity
- Arguments: \%entity_data
- Return Value: $entity
Creates a new entity object of the resultset's type and returns it. The row is not inserted into the database at this point, call "save" in DBIx::EAV::Entity to do that. Calling "in_storage" in DBIx::EAV::Entity will tell you whether the entity object has been inserted or not.
# create a new entity, do some modifications...
my $cd = $eav->resultset('CD')->new_entity({ title => 'CD1' });
$cd->set('year', 2016);
# now insert it
$cd->save;
insert
- Arguments: \%entity_data
- Return Value: $entity
Attempt to create a single new entity or a entity with multiple related entities in the type represented by the resultset (and related types). This will not check for duplicate entities before inserting, use "find_or_create" to do that.
To create one entity for this resultset, pass a hashref of key/value pairs representing the attributes of the "type" and the values you wish to store. If the appropriate relationships are set up, you can also pass related data.
To create related entities, pass a hashref of related-object attribute values keyed on the relationship name. If the relationship is of type has_many
or many_to_many
- pass an arrayref of hashrefs. The process will correctly identify the relationship type and side, and will transparently populate the "entitiy_relationships table". This can be applied recursively, and will work correctly for a structure with an arbitrary depth and width, as long as the relationships actually exists and the correct data has been supplied.
Instead of hashrefs of plain related data (key/value pairs), you may also pass new or inserted objects. New objects (not inserted yet, see "new_entity"), will be inserted into their appropriate types.
Effectively a shortcut for ->new_entity(\%entity_data)->save
.
Example of creating a new entity.
my $cd1 = $cds_rs->insert({
title => 'CD1',
year => 2016
});
Example of creating a new entity and also creating entities in a related has_many
resultset. Note Arrayref for tracks
.
my $cd1 = $eav->resultset('CD')->insert({
title => 'CD1',
year => 2016
tracks => [
{ title => 'Track1', duration => ... },
{ title => 'Track2', duration => ... },
{ title => 'Track3', duration => ... }
]
});
Example of passing existing objects as related data.
my @tags = $eav->resultset('Tag')->search(\%where);
my $article = $eav->resultset('Article')->insert({
title => 'Some Article',
content => '...',
tags => \@tags
});
- WARNING
-
When subclassing ResultSet never attempt to override this method. Since it is a simple shortcut for
$self->new_entity($data)->save
, a lot of the internals simply never call it, so your override will be bypassed more often than not. Override either "new" in DBIx::EAV::Entity or "save" in DBIx::EAV::Entity depending on how early in the "insert" process you need to intervene.
populate
- Arguments: \@entites
- Return Value: @inserted_entities
Shortcut for inserting multiple entities at once. Returns a list of inserted entities.
my @cds = $eav->resultset('CD')->populate([
{ title => 'CD1', ... },
{ title => 'CD2', ... },
{ title => 'CD3', ... }
]);
count
Performs an SQL COUNT
with the same query as the resultset was built with to find the number of elements. Passing arguments is equivalent to $rs->search($cond, \%attrs)->count
delete
Deletes the entities matching \%where condition without fetching them first. This will run faster, at the cost of related entities not being casdade deleted. Call "delete_all" if you want to cascade delete related entities.
When "database_cascade_delete" in DBIx::EAV is enabled, the delete operation is done in a single query. Otherwise one more query is needed for each of the values table and another for the relationship link table.
- WARNING
-
This method requires database support for
DELETE ... JOIN
. Since the current implementation of DBIx::EAV is only tested against MySQL and SQLite, this method calls "delete_all" if SQLite database is detected.
delete_all
Fetches all objects and deletes them one at a time via "delete" in DBIx::EAV::Entity. Note that delete_all
will cascade delete related entities, while "delete" will not.
QUERY OPTIONS
limit
Specifies the maximum number of rows for direct retrieval or the number of rows per page if the page option or method is used.
offset
Specifies the (zero-based) row number for the first row to be returned, or the of the first row of the first page if paging is used.
page
NOT IMPLEMENTED.
group_by
A arrayref of columns to group by. Can include columns of joined tables.
group_by => [qw/ column1 column2 ... /]
having
The HAVING operator specifies a secondary condition applied to the set after the grouping calculations have been done. In other words it is a constraint just like "QUERY" (and accepting the same SQL::Abstract syntax) applied to the data as it exists after GROUP BY has taken place. Specifying "having" without "group_by" is a logical mistake, and a fatal error on most RDBMS engines. Valid fields for criteria are all known attributes, relationships and related attributes for the type this cursor is bound to.
E.g.
$eav->resultset('CD')->search(undef, {
'+select' => { count => 'tracks' }, # alias 'count_tracks' created automatically
group_by => ['me.id'],
having => { count_tracks => { '>' => 5 } }
});
Althought literal SQL is supported, you must know the actual alias and column names used in the generated SQL statement.
having => \[ 'count(cds_link.) >= ?', 100 ]
Set the debug flag to get the SQL statements printed to stderr.
distinct
Set to 1 to automatically generate a "group_by" clause based on the selection (including intelligent handling of "order_by" contents). Note that the group criteria calculation takes place over the final selection. This includes any "+columns", "+select" or "order_by" additions in subsequent "search" calls, and standalone columns selected via DBIx::Class::ResultSetColumn ("get_column"). A notable exception are the extra selections specified via "prefetch" - such selections are explicitly excluded from group criteria calculations.
If the cursor also explicitly has a "group_by" attribute, this setting is ignored and an appropriate warning is issued.
subtype_depth
- Value: $depth
-
Specifies how deep in the type hierarchy you want the query to go. By default its 0, and the query is restricted to the type this cursor is bound to. Even though you can use this option to find entities of subtypes, you cannot use the subtypes own attributes in the query. So if you need to do a subtype query, ensure all attributes needed for the query are defined on the parent type.
# Example entity types: # Product [attrs: name, price, description] # HardDrive [extends: Product] [attrs: rpm, capacity] # Monitor [extends: Product] [attrs: resolution, contrast_ratio] # FancyMonitor [extends: Monitor] [attrs: fancy_feature] # this query won't find any HardDrive or Monitor, only Product entities $eav->resultset('Product')->search({ price => { '<' => 500 } }); # this also finds HardDrive and Monitor entities $eav->resultset('Product')->search( { price => { '<' => 500 } }, # subtype's attributes are not allowed { subtype_depth => 1 } ); # this query also finds FancyMonitor $eav->resultset('Product')->search( \%where, { subtype_depth => 2 } );
prefetch
NOT IMPLEMENTED.
LICENSE
Copyright (C) Carlos Fernando Avila Gratz.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
AUTHOR
Carlos Fernando Avila Gratz <cafe@kreato.com.br>