Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,144 @@
=head1 NAME
DBIx::Class::Manual::Component - Developing DBIx::Class Components
=head1 WHAT IS A COMPONENT
A component is a module that can be added in to your DBIx::Class
classes to provide extra functionality. A good example is the PK::Auto
component which automatically retrieves primary keys that the database
itself creates, after the insert has happened.
=head1 USING
Components are loaded using the load_components() method within your
DBIx::Class classes.
package My::Thing;
use base qw( DBIx::Class::Core );
__PACKAGE__->load_components(qw/InflateColumn::DateTime TimeStamp/);
Generally you do not want to specify the full package name
of a component, instead take off the DBIx::Class:: part of
it and just include the rest. If you do want to load a
component outside of the normal namespace you can do so
by prepending the component name with a +.
__PACKAGE__->load_components(qw/ +My::Component /);
Once a component is loaded all of its methods, or otherwise,
that it provides will be available in your class.
The order in which is you load the components may be very
important, depending on the component. If you are not sure,
then read the docs for the components you are using and see
if they mention anything about the order in which you should
load them.
=head1 CREATING COMPONENTS
Making your own component is very easy.
package DBIx::Class::MyComp;
use base qw(DBIx::Class);
# Create methods, accessors, load other components, etc.
1;
When a component is loaded it is included in the calling
class' inheritance chain using L<Class::C3>. As well as
providing custom utility methods, a component may also
override methods provided by other core components, like
L<DBIx::Class::Row> and others. For example, you
could override the insert and delete methods.
sub insert {
my $self = shift;
# Do stuff with $self, like set default values.
return $self->next::method( @_ );
}
sub delete {
my $self = shift;
# Do stuff with $self.
return $self->next::method( @_ );
}
Now, the order that a component is loaded is very important. Components
that are loaded first are the first ones in the inheritance stack. So, if
you override insert() but the DBIx::Class::Row component is loaded first
then your insert() will never be called, since the DBIx::Class::Row insert()
will be called first. If you are unsure as to why a given method is not
being called try printing out the current linearized MRO.
print join ', ' => mro::get_linear_isa('YourClass::Name');
=head1 EXISTING COMPONENTS
=head2 Extra
These components provide extra functionality beyond
basic functionality that you can't live without.
L<DBIx::Class::CDBICompat> - Class::DBI Compatibility layer.
L<DBIx::Class::FormTools> - Build forms with multiple interconnected objects.
L<DBIx::Class::HTMLWidget> - Like FromForm but with DBIx::Class and HTML::Widget.
L<DBIx::Class::Ordered> - Modify the position of objects in an ordered list.
L<DBIx::Class::PK::Auto> - Retrieve automatically created primary keys upon insert.
L<DBIx::Class::QueriesTime> - Display the amount of time it takes to run queries.
L<DBIx::Class::RandomStringColumns> - Declare virtual columns that return random strings.
L<DBIx::Class::UUIDColumns> - Implicit UUID columns.
L<DBIx::Class::WebForm> - CRUD methods.
=head2 Experimental
These components are under development, their interfaces may
change, they may not work, etc. So, use them if you want, but
be warned.
L<DBIx::Class::Validation> - Validate all data before submitting to your database.
=head2 Core
These are the components that all, or nearly all, people will use
without even knowing it. These components provide most of
DBIx::Class' functionality.
L<DBIx::Class::Core> - Loads various components that "most people" would want.
L<DBIx::Class::AccessorGroup> - Lets you build groups of accessors.
L<DBIx::Class::DB> - Non-recommended classdata schema component.
L<DBIx::Class::InflateColumn> - Automatically create objects from column data.
L<DBIx::Class::PK> - This class contains methods for handling primary keys and methods depending on them.
L<DBIx::Class::Relationship> - Inter-table relationships.
L<DBIx::Class::ResultSourceProxy::Table> - Provides a classdata table object and method proxies.
L<DBIx::Class::Row> - Basic row methods.
=head1 SEE ALSO
L<DBIx::Class::Manual::Cookbook>
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
=head1 NAME
DBIx::Class::Manual::DocMap - What documentation do we have?
=head1 Manuals
=over 4
=item L<DBIx::Class::Manual> - User's Manual overview.
=item L<DBIx::Class::Manual::QuickStart> - Up and running with DBIC in 10 minutes.
=item L<DBIx::Class::Manual::Intro> - More detailed introduction to setting up and using DBIx::Class.
=item L<DBIx::Class::Manual::SQLHackers> - How to use DBIx::Class if you know SQL (external, available on CPAN)
=item L<DBIx::Class::Manual::Joining> - Joining tables with DBIx::Class.
=item L<DBIx::Class::Manual::Features> - A boatload of DBIx::Class features with links to respective documentation.
=item L<DBIx::Class::Manual::Glossary> - What do all those terms mean?
=item L<DBIx::Class::Manual::Cookbook> - Various short recipes on how to do things.
=item L<DBIx::Class::Manual::FAQ> - Frequently Asked Questions, gathered from IRC and the mailing list.
=item L<DBIx::Class::Manual::Troubleshooting> - What to do if things go wrong (diagnostics of known error messages).
=back
=head1 Some essential reference documentation
The first two list items are the most important.
=over 4
=item L<DBIx::Class::ResultSet/search> - Selecting and manipulating sets.
The DSL (mini-language) for query composition is only partially explained there,
see L<SQL::Abstract::Classic/WHERE CLAUSES> for the complete details.
=item L<C<$schema>::Result::C<$resultclass>|DBIx::Class::Manual::ResultClass>
- Classes representing a single result (row) from a DB query.
Such classes normally subclass L<DBIx::Class::Core>, the methods inherited
from L<DBIx::Class::Row|DBIx::Class::Row/METHODS> and
L<DBIx::Class::Relationship::Base|DBIx::Class::Relationship::Base/METHODS>
are used most often.
=item L<DBIx::Class::ResultSetColumn> - Perform operations on a single column of a ResultSet.
=item L<DBIx::Class::ResultSource> - Source/Table definition functions.
=item L<DBIx::Class::Schema> - Overall sources, and connection container.
=item L<DBIx::Class::Relationship> - Simple relationship declarations.
=item L<DBIx::Class::Relationship::Base> - Relationship declaration details.
=item L<DBIx::Class::InflateColumn> - Making objects out of your column values.
=back
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,115 @@
=head1 NAME
DBIx::Class::Manual::Example - Simple CD database example
=head1 DESCRIPTION
This tutorial will guide you through the process of setting up and
testing a very basic CD database using SQLite, with DBIx::Class::Schema
as the database frontend.
The database structure is based on the following rules:
An artist can have many cds, and each cd belongs to just one artist.
A cd can have many tracks, and each track belongs to just one cd.
The database is implemented with the following:
table 'artist' with columns: artistid, name
table 'cd' with columns: cdid, artistid, title, year
table 'track' with columns: trackid, cdid, title
Each of the table's first columns is the primary key; any subsequent
keys are foreign keys.
=head2 Installation
You'll need to install DBIx::Class via CPAN, and you'll also need to
install sqlite3 (not sqlite) if it's not already intalled.
=head3 The database/tables/data
Your distribution already comes with a pre-filled SQLite database
F<examples/Schema/db/example.db>. You can see it by e.g.
cpanm --look DBIx::Class
If for some reason the file is unreadable on your system, you can
recreate it as follows:
cp -a <unpacked-DBIC-tarball>/examples/Schema dbicapp
cd dbicapp
rm db/example.db
sqlite3 db/example.db < db/example.sql
perl insertdb.pl
=head3 Testing the database
Enter the example Schema directory
cd <unpacked-DBIC-tarball>/examples/Schema
Run the script testdb.pl, which will test that the database has
successfully been filled.
When this script is run, it should output the following:
get_tracks_by_cd(Bad):
Leave Me Alone
Smooth Criminal
Dirty Diana
get_tracks_by_artist(Michael Jackson):
Billie Jean (from the CD 'Thriller')
Beat It (from the CD 'Thriller')
Leave Me Alone (from the CD 'Bad')
Smooth Criminal (from the CD 'Bad')
Dirty Diana (from the CD 'Bad')
get_cd_by_track(Stan):
The Marshall Mathers LP has the track 'Stan'.
get_cds_by_artist(Michael Jackson):
Thriller
Bad
get_artist_by_track(Dirty Diana):
Michael Jackson recorded the track 'Dirty Diana'.
get_artist_by_cd(The Marshall Mathers LP):
Eminem recorded the CD 'The Marshall Mathers LP'.
=head3 Discussion about the results
The data model defined in this example has an artist with multiple CDs,
and a CD with multiple tracks; thus, it's simple to traverse from a
track back to a CD, and from there back to an artist. This is
demonstrated in the get_tracks_by_artist routine, where we easily walk
from the individual track back to the title of the CD that the track
came from ($track->cd->title).
Note also that in the get_tracks_by_cd and get_tracks_by_artist
routines, the result set is called multiple times with the 'next'
iterator. In contrast, get_cd_by_track uses the 'first' result set
method, since only one CD is expected to have a specific track.
This example uses L<DBIx::Class::Schema/load_namespaces> to load in the
appropriate L<Result|DBIx::Class::Manual::ResultClass> classes from the
C<MyApp::Schema::Result> namespace, and any required
L<ResultSet|DBIx::Class::ResultSet> classes from the
C<MyApp::Schema::ResultSet> namespace (although we did not add, nor needed
any such classes in this example).
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
=cut

View File

@@ -0,0 +1,706 @@
=head1 NAME
DBIx::Class::Manual::FAQ - Frequently Asked Questions (in theory)
=head1 DESCRIPTION
This document is intended as an anti-map of the documentation. If you
know what you want to do, but not how to do it in L<DBIx::Class>, then
look here. It does B<not> contain much code or examples, it just gives
explanations and pointers to the correct pieces of documentation to
read.
=head1 FAQs
How Do I:
=head2 Getting started
=over 4
=item .. create a database to use?
First, choose a database. For testing/experimenting, we recommend
L<DBD::SQLite>, which is a self-contained small database (i.e. all you
need to do is to install L<DBD::SQLite> from CPAN, and it works).
Next, spend some time defining which data you need to store, and how
it relates to the other data you have. For some help on normalisation,
go to L<http://b62.tripod.com/doc/dbbase.htm>.
Now, decide whether you want to have the database itself be the
definitive source of information about the data layout, or your
DBIx::Class schema. If it's the former, look up the documentation for
your database, eg. L<http://sqlite.org/lang_createtable.html>, on how
to create tables, and start creating them. For a nice universal
interface to your database, you can try L<DBI::Shell>. If you decided
on the latter choice, read the FAQ on setting up your classes
manually, and the one on creating tables from your schema.
=item .. use DBIx::Class with L<Catalyst>?
Install L<Catalyst::Model::DBIC::Schema> from CPAN. See its
documentation, or below, for further details.
=item .. set up my DBIx::Class classes automatically from my database?
Install L<DBIx::Class::Schema::Loader> from CPAN, and read its documentation.
=item .. set up my DBIx::Class classes manually?
Look at the L<DBIx::Class::Manual::Example> and come back here if you get lost.
=item .. create my database tables from my DBIx::Class schema?
Create your classes manually, as above. Write a script that calls
L<DBIx::Class::Schema/deploy>. See there for details, or the
L<DBIx::Class::Manual::Cookbook>.
=item .. store/retrieve Unicode data in my database?
Make sure you database supports Unicode and set the connect
attributes appropriately - see
L<DBIx::Class::Manual::Cookbook/Using Unicode>
=item .. connect to my database?
Once you have created all the appropriate table/source classes, and an
overall L<Schema|DBIx::Class::Schema> class, you can start using
them in an application. To do this, you need to create a central
Schema object, which is used to access all the data in the various
tables. See L<DBIx::Class::Schema/connect> for details. The actual
connection does not happen until you actually request data, so don't
be alarmed if the error from incorrect connection details happens a
lot later.
=item .. use DBIx::Class across multiple databases?
If your database server allows you to run queries across multiple
databases at once, then so can DBIx::Class. All you need to do is make
sure you write the database name as part of the
L<table|DBIx::Class::ResultSourceProxy::Table/table> call. Eg:
__PACKAGE__->table('mydb.mytablename');
And load all the Result classes for both / all databases by calling
L<DBIx::Class::Schema/load_namespaces>.
=item .. use DBIx::Class across PostgreSQL/DB2/Oracle schemas?
Add the name of the schema to the table name, when invoking
L<table|DBIx::Class::ResultSourceProxy::Table/table>, and make sure the user
you are about to connect as has permissions to read/write all the
schemas/tables as necessary.
=back
=head2 Relationships
=over 4
=item .. tell DBIx::Class about relationships between my tables?
There are a variety of relationship types that come pre-defined for
you to use. These are all listed in L<DBIx::Class::Relationship>. If
you need a non-standard type, or more information, look in
L<DBIx::Class::Relationship::Base>.
=item .. define a one-to-many relationship?
This is called a C<has_many> relationship on the one side, and a
C<belongs_to> relationship on the many side. Currently these need to
be set up individually on each side. See L<DBIx::Class::Relationship>
for details.
=item .. define a relationship where this table contains another table's primary key? (foreign key)
Create a C<belongs_to> relationship for the field containing the
foreign key. See L<DBIx::Class::Relationship/belongs_to>.
=item .. define a foreign key relationship where the key field may contain NULL?
Just create a C<belongs_to> relationship, as above. If the column is
NULL then the inflation to the foreign object will not happen. This
has a side effect of not always fetching all the relevant data, if you
use a nullable foreign-key relationship in a JOIN, then you probably
want to set the C<join_type> to C<left>.
=item .. define a relationship where the key consists of more than one column?
Instead of supplying a single column name, all relationship types also
allow you to supply a hashref containing the condition across which
the tables are to be joined. The condition may contain as many fields
as you like. See L<DBIx::Class::Relationship::Base>.
=item .. define a relationship bridge across an intermediate table? (many-to-many)
The term 'relationship' is used loosely with many_to_many as it is not considered a
relationship in the fullest sense. For more info, read the documentation on L<DBIx::Class::Relationship/many_to_many>.
=item .. stop DBIx::Class from attempting to cascade deletes on my has_many and might_have relationships?
By default, DBIx::Class cascades deletes and updates across
C<has_many> and C<might_have> relationships. You can disable this
behaviour on a per-relationship basis by supplying
C<< cascade_delete => 0 >> in the relationship attributes.
The cascaded operations are performed after the requested delete or
update, so if your database has a constraint on the relationship, it
will have deleted/updated the related records or raised an exception
before DBIx::Class gets to perform the cascaded operation.
See L<DBIx::Class::Relationship>.
=item .. use a relationship?
Use its name. An accessor is created using the name. See examples in
L<DBIx::Class::Manual::Cookbook/USING RELATIONSHIPS>.
=back
=head2 Searching
=over 4
=item .. search for data?
Create a C<$schema> object, as mentioned above in L</.. connect to my
database?>. Find the
L<ResultSet|DBIx::Class::Manual::Glossary/ResultSet> that you want to
search in, by calling C<< $schema->resultset('MySource') >> and call
C<search> on it. See L<DBIx::Class::ResultSet/search>.
=item .. search using database functions?
Supplying something like:
->search({'mydatefield' => 'now()'})
to search, will probably not do what you expect. It will quote the
text "now()", instead of trying to call the function. To provide
literal, unquoted text you need to pass in a scalar reference, like
so:
->search({'mydatefield' => \'now()'})
=item .. sort the results of my search?
Supply a list of columns you want to sort by to the C<order_by>
attribute. See L<DBIx::Class::ResultSet/order_by>.
=item .. sort my results based on fields I've aliased using C<as>?
You didn't alias anything, since L<as|DBIx::Class::ResultSet/as>
B<has nothing to do> with the produced SQL. See
L<DBIx::Class::ResultSet/select> for details.
=item .. group the results of my search?
Supply a list of columns you want to group on, to the C<group_by>
attribute, see L<DBIx::Class::ResultSet/group_by>.
=item .. group my results based on fields I've aliased using C<as>?
You don't. See the explanation on ordering by an alias above.
=item .. filter the results of my search?
The first argument to C<search> is a hashref of accessor names and
values to filter them by, for example:
->search({'created_time' => { '>=', '2006-06-01 00:00:00' } })
Note that to use a function here you need to make it a scalar
reference:
->search({'created_time' => { '>=', \'yesterday()' } })
=item .. search in several tables simultaneously?
To search in two related tables, you first need to set up appropriate
relationships between their respective classes. When searching you
then supply the name of the relationship to the C<join> attribute in
your search, for example when searching in the Books table for all the
books by the author "Fred Bloggs":
->search({'authors.name' => 'Fred Bloggs'}, { join => 'authors' })
The type of join created in your SQL depends on the type of
relationship between the two tables, see L<DBIx::Class::Relationship>
for the join used by each relationship.
=item .. create joins with conditions other than column equality?
Currently, L<DBIx::Class> can only create join conditions using
equality, so you're probably better off creating a C<view> in your
database, and using that as your source. A C<view> is a stored SQL
query, which can be accessed similarly to a table, see your database
documentation for details.
=item .. search with an SQL function on the left hand side?
To use an SQL function on the left hand side of a comparison you currently need
to resort to literal SQL:
->search( \[ 'YEAR(date_of_birth) = ?', 1979 ] );
=item .. find more help on constructing searches?
Behind the scenes, DBIx::Class uses L<SQL::Abstract::Classic> to help construct
its SQL searches. So if you fail to find help in the
L<DBIx::Class::Manual::Cookbook>, try looking in the L<SQL::Abstract::Classic>
documentation.
=item .. make searches in Oracle (10gR2 and newer) case-insensitive?
To make Oracle behave like most RDBMS use on_connect_do to issue
alter session statements on database connection establishment:
->on_connect_do("ALTER SESSION SET NLS_COMP = 'LINGUISTIC'");
->on_connect_do("ALTER SESSION SET NLS_SORT = '<NLS>_CI'");
e.g.
->on_connect_do("ALTER SESSION SET NLS_SORT = 'BINARY_CI'");
->on_connect_do("ALTER SESSION SET NLS_SORT = 'GERMAN_CI'");
=item .. format a DateTime object for searching?
L<search|DBIx::Class::ResultSet/search> and L<find|DBIx::Class::ResultSet/find>
do not take L<DBIx::Class::InflateColumn> into account, and so your L<DateTime>
object will not be correctly deflated into a format your RDBMS expects.
The L<datetime_parser|DBIx::Class::Storage::DBI/datetime_parser> method on your
storage object can be used to return the object that would normally do this, so
it's easy to do it manually:
my $dtf = $schema->storage->datetime_parser;
my $rs = $schema->resultset('users')->search(
{
signup_date => {
-between => [
$dtf->format_datetime($dt_start),
$dtf->format_datetime($dt_end),
],
}
},
);
With in a Result Class method, you can get this from the
L<C<result_source>|DBIx::Class::Row/result_source>.
my $dtf = $self->result_source->storage->datetime_parser;
This kludge is necessary only for conditions passed to
L<search|DBIx::Class::ResultSet/search> and L<DBIx::Class::ResultSet/find>,
whereas L<create|DBIx::Class::ResultSet/create> and L<DBIx::Class::Row/update>
(but not L<DBIx::Class::ResultSet/update>) are
L<DBIx::Class::InflateColumn>-aware and will do the right thing when supplied
an inflated L<DateTime> object.
=back
=head2 Fetching data
=over 4
=item .. fetch as much data as possible in as few select calls as possible?
See the prefetch examples in the L<Cookbook|DBIx::Class::Manual::Cookbook>.
=item .. fetch a whole column of data instead of a row?
Call C<get_column> on a L<DBIx::Class::ResultSet>. This returns a
L<DBIx::Class::ResultSetColumn>. See its documentation and the
L<Cookbook|DBIx::Class::Manual::Cookbook> for details.
=item .. fetch a formatted column?
In your table schema class, create a "private" column accessor with:
__PACKAGE__->add_columns(my_column => { accessor => '_hidden_my_column' });
Then, in the same class, implement a subroutine called "my_column" that
fetches the real value and does the formatting you want.
See the L<Cookbook|DBIx::Class::Manual::Cookbook> for more details.
=item .. fetch a single (or topmost) row?
Use the L<DBIx::Class::ResultSet/rows> and
L<DBIx::Class::ResultSet/order_by> attributes to order your data and
pick off a single row.
See also L<DBIx::Class::Manual::Cookbook/Retrieve one and only one row from a resultset>.
A less readable way is to ask a regular search to return 1 row, using
L<DBIx::Class::ResultSet/slice>:
->search->(undef, { order_by => "id DESC" })->slice(0)
which (if supported by the database) will use LIMIT/OFFSET to hint to the
database that we really only need one row. This can result in a significant
speed improvement. The method using L<DBIx::Class::ResultSet/single> mentioned
in the cookbook can do the same if you pass a C<rows> attribute to the search.
=item .. refresh a row from storage?
Use L<DBIx::Class::Row/discard_changes>.
$result->discard_changes
Discarding changes and refreshing from storage are two sides of the same coin. When you
want to discard your local changes, just re-fetch the row from storage. When you want
to get a new, fresh copy of the row, just re-fetch the row from storage.
L<DBIx::Class::Row/discard_changes> does just that by re-fetching the row from storage
using the row's primary key.
=item .. fetch my data a "page" at a time?
Pass the C<rows> and C<page> attributes to your search, eg:
->search({}, { rows => 10, page => 1});
=item .. get a count of all rows even when paging?
Call C<pager> on the paged resultset, it will return a L<pager object
|DBIx::Class::ResultSet::Pager> with an API/behavior identical to that
of L<Data::Page from late 2009 through late 2019
|https://metacpan.org/pod/release/LBROCARD/Data-Page-2.02/lib/Data/Page.pm>.
Calling C<total_entries> on the pager will return the correct total.
C<count> on the resultset will only return the total number in the page.
=back
=head2 Inserting and updating data
=over 4
=item .. insert a row with an auto incrementing primary key?
This happens automatically. After
L<creating|DBIx::Class::ResultSet/create> a result object, the primary
key value created by your database can be fetched by calling C<id> (or
the access of your primary key column) on the object.
=item .. insert a row with a primary key that uses a sequence?
You need to create a trigger in your database that updates your
primary key field from the sequence. To help PK::Auto find the next
key value, you can tell it the name of the sequence in the
C<column_info> supplied with C<add_columns>.
->add_columns({ id => { sequence => 'mysequence', auto_nextval => 1 } });
=item .. insert many rows of data efficiently?
The C<populate> method in L<DBIx::Class::ResultSet> provides
efficient bulk inserts.
L<DBIx::Class::Fixtures> provides an alternative way to do this.
=item .. update a collection of rows at the same time?
Create a resultset using a C<search>, to filter the rows of data you
would like to update, then call C<update> on the resultset to change all
the rows at once.
=item .. use database functions when updating rows?
=item .. update a column using data from another column?
To stop the column name from being quoted, you'll need to tell DBIC
that the right hand side is an SQL identifier (it will be quoted
properly if you have quoting enabled):
->update({ somecolumn => { -ident => 'othercolumn' } })
This method will not retrieve the new value and put it in your Row
object. To fetch the new value, use the C<discard_changes> method on
the Row.
# will return the scalar reference:
$result->somecolumn()
# issue a select using the PK to re-fetch the row data:
$result->discard_changes();
# Now returns the correct new value:
$result->somecolumn()
To update and refresh at once, chain your calls:
$result->update({ 'somecolumn' => { -ident => 'othercolumn' } })->discard_changes;
=item .. store JSON/YAML in a column and have it deflate/inflate automatically?
You can use L<DBIx::Class::InflateColumn> to accomplish YAML/JSON storage transparently.
If you want to use JSON, then in your table schema class, do the following:
use JSON;
__PACKAGE__->add_columns(qw/ ... my_column ../)
__PACKAGE__->inflate_column('my_column', {
inflate => sub { jsonToObj(shift) },
deflate => sub { objToJson(shift) },
});
For YAML, in your table schema class, do the following:
use YAML;
__PACKAGE__->add_columns(qw/ ... my_column ../)
__PACKAGE__->inflate_column('my_column', {
inflate => sub { YAML::Load(shift) },
deflate => sub { YAML::Dump(shift) },
});
This technique is an easy way to store supplemental unstructured data in a table. Be
careful not to overuse this capability, however. If you find yourself depending more
and more on some data within the inflated column, then it may be time to factor that
data out.
=back
=head2 Custom methods in Result classes
You can add custom methods that do arbitrary things, even to unrelated tables.
For example, to provide a C<< $book->foo() >> method which searches the
cd table, you'd could add this to Book.pm:
sub foo {
my ($self, $col_data) = @_;
return $self->result_source->schema->resultset('cd')->search($col_data);
}
And invoke that on any Book Result object like so:
my $rs = $book->foo({ title => 'Down to Earth' });
When two tables ARE related, L<DBIx::Class::Relationship::Base> provides many
methods to find or create data in related tables for you. But if you want to
write your own methods, you can.
For example, to provide a C<< $book->foo() >> method to manually implement
what create_related() from L<DBIx::Class::Relationship::Base> does, you could
add this to Book.pm:
sub foo {
my ($self, $rel_name, $col_data) = @_;
return $self->related_resultset($rel_name)->create($col_data);
}
Invoked like this:
my $author = $book->foo('author', { name => 'Fred' });
=head2 Misc
=over 4
=item How do I store my own (non-db) data in my DBIx::Class objects?
You can add your own data accessors to your Result classes.
One method is to use the built in mk_group_accessors (via L<Class::Accessor::Grouped>)
package App::Schema::Result::MyTable;
use parent 'DBIx::Class::Core';
__PACKAGE__->table('foo'); #etc
__PACKAGE__->mk_group_accessors('simple' => qw/non_column_data/); # must use simple group
And another method is to use L<Moose> with your L<DBIx::Class> package.
package App::Schema::Result::MyTable;
use Moose; # import Moose
use Moose::Util::TypeConstraint; # import Moose accessor type constraints
extends 'DBIx::Class::Core'; # Moose changes the way we define our parent (base) package
has 'non_column_data' => ( is => 'rw', isa => 'Str' ); # define a simple attribute
__PACKAGE__->table('foo'); # etc
With either of these methods the resulting use of the accessor would be
my $result;
# assume that somewhere in here $result will get assigned to a MyTable row
$result->non_column_data('some string'); # would set the non_column_data accessor
# some other stuff happens here
$result->update(); # would not inline the non_column_data accessor into the update
=item How do I use DBIx::Class objects in my TT templates?
Like normal objects, mostly. However you need to watch out for TT
calling methods in list context. When calling relationship accessors
you will not get resultsets, but a list of all the related objects.
Use the L<DBIx::Class::ResultSet/search_rs> method, or the
relationship accessor methods ending with "_rs" to work around this
issue.
See also L<DBIx::Class::Relationship/has_many>.
=item See the SQL statements my code is producing?
Set the shell environment variable C<DBIC_TRACE> to a true value.
For more info see L<DBIx::Class::Storage> for details of how
to turn on debugging in the environment, pass your own filehandle to
save debug to, or create your own callback.
=item Why didn't my search run any SQL?
L<DBIx::Class> runs the actual SQL statement as late as possible, thus
if you create a resultset using C<search> in scalar context, no query
is executed. You can create further resultset refinements by calling
search again or relationship accessors. The SQL query is only run when
you ask the resultset for an actual result object.
=item How do I deal with tables that lack a primary key?
If your table lacks a primary key, DBIx::Class can't work out which row
it should operate on, for example to delete or update. However, a
UNIQUE constraint on one or more columns allows DBIx::Class to uniquely
identify the row, so you can tell L<DBIx::Class::ResultSource> these
columns act as a primary key, even if they don't from the database's
point of view:
$resultset->set_primary_key(@column);
=item How do I make my program start faster?
Look at the tips in L<DBIx::Class::Manual::Cookbook/"STARTUP SPEED">
=item How do I reduce the overhead of database queries?
You can reduce the overhead of object creation within L<DBIx::Class>
using the tips in L<DBIx::Class::Manual::Cookbook/"Skip result object creation for faster results">
and L<DBIx::Class::Manual::Cookbook/"Get raw data for blindingly fast results">
=item How do I override a run time method (e.g. a relationship accessor)?
If you need access to the original accessor, then you must "wrap around" the original method.
You can do that either with L<Moose::Manual::MethodModifiers> or L<Class::Method::Modifiers>.
The code example works for both modules:
package Your::Schema::Group;
use Class::Method::Modifiers;
# ... declare columns ...
__PACKAGE__->has_many('group_servers', 'Your::Schema::GroupServer', 'group_id');
__PACKAGE__->many_to_many('servers', 'group_servers', 'server');
# if the server group is a "super group", then return all servers
# otherwise return only servers that belongs to the given group
around 'servers' => sub {
my $orig = shift;
my $self = shift;
return $self->$orig(@_) unless $self->is_super_group;
return $self->result_source->schema->resultset('Server')->all;
};
If you just want to override the original method, and don't care about the data
from the original accessor, then you have two options. Either use
L<Method::Signatures::Simple> that does most of the work for you, or do
it the "dirty way".
L<Method::Signatures::Simple> way:
package Your::Schema::Group;
use Method::Signatures::Simple;
# ... declare columns ...
__PACKAGE__->has_many('group_servers', 'Your::Schema::GroupServer', 'group_id');
__PACKAGE__->many_to_many('servers', 'group_servers', 'server');
# The method keyword automatically injects the annoying my $self = shift; for you.
method servers {
return $self->result_source->schema->resultset('Server')->search({ ... });
}
The dirty way:
package Your::Schema::Group;
use Sub::Name;
# ... declare columns ...
__PACKAGE__->has_many('group_servers', 'Your::Schema::GroupServer', 'group_id');
__PACKAGE__->many_to_many('servers', 'group_servers', 'server');
*servers = subname servers => sub {
my $self = shift;
return $self->result_source->schema->resultset('Server')->search({ ... });
};
=back
=head2 Notes for CDBI users
=over 4
=item Is there a way to make an object auto-stringify itself as a
particular column or group of columns (a-la cdbi Stringfy column
group, or stringify_self method) ?
See L<DBIx::Class::Manual::Cookbook/Stringification>
=back
=head2 Troubleshooting
=over 4
=item Help, I can't connect to postgresql!
If you get an error such as:
DBI connect('dbname=dbic','user',...) failed: could not connect to server:
No such file or directory Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Likely you have/had two copies of postgresql installed simultaneously, the
second one will use a default port of 5433, while L<DBD::Pg> is compiled with a
default port of 5432.
You can change the port setting in C<postgresql.conf>.
=item I've lost or forgotten my mysql password
Stop mysqld and restart it with the --skip-grant-tables option.
Issue the following statements in the mysql client.
UPDATE mysql.user SET Password=PASSWORD('MyNewPass') WHERE User='root';
FLUSH PRIVILEGES;
Restart mysql.
Taken from:
L<http://dev.mysql.com/doc/refman/5.1/en/resetting-permissions.html>.
=back
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,677 @@
=head1 NAME
DBIx::Class::Manual::Features - A boatload of DBIx::Class features with links to respective documentation
=head1 META
=head2 Large Community
There are L<hundres of DBIC contributors|DBIx::Class/AUTHORS> listed in
F<AUTHORS>. That ranges from documentation help, to test help, to added
features, to entire database support.
=head2 Active Community
Currently (June 9, 2010) 6 active branches (committed to
in the last two weeks) in git. Last release (0.08122)
had 14 new features, and 16 bug fixes. Of course that
L<ebbs and flows|https://metacpan.org/changes/distribution/DBIx-Class>.)
=head2 Responsive Community
=over 1
=item I needed MSSQL order-by support; the community helped me add support
=item generally very welcoming of people willing to help
=back
=head1 General ORM
These are things that are in most other ORMs, but are still reasons to use
DBIC over raw SQL.
=head2 Cross DB
The vast majority of code should run on all databases without needing tweaking
=head2 Basic CRUD
=over 1
=item C - Create
=item R - Retrieve
=item U - Update
=item D - Delete
=back
=head2 SQL: Create
my $sth = $dbh->prepare('
INSERT INTO books
(title, author_id)
values (?,?)
');
$sth->execute( 'A book title', $author_id );
=head2 DBIC: Create
my $book = $book_rs->create({
title => 'A book title',
author_id => $author_id,
});
See L<DBIx::Class::ResultSet/create>
=over 1
=item No need to pair placeholders and values
=item Automatically gets autoincremented id for you
=item Transparently uses INSERT ... RETURNING for databases that support it
=back
=head2 SQL: Read
my $sth = $dbh->prepare('
SELECT title,
authors.name as author_name
FROM books, authors
WHERE books.author = authors.id
');
while ( my $book = $sth->fetchrow_hashref ) {
say "Author of $book->{title} is $book->{author_name}";
}
=head2 DBIC: Read
my $book = $book_rs->find($book_id);
or
my $book = $book_rs->search({ title => 'A book title' }, { rows => 1 })->next;
or
my @books = $book_rs->search({ author => $author_id })->all;
or
while( my $book = $books_rs->next ) {
printf "Author of %s is %s\n", $book->title, $book->author->name;
}
See L<DBIx::Class::ResultSet/find>, L<DBIx::Class::ResultSet/search>, L<DBIx::Class::ResultSet/next>, and L<DBIx::Class::ResultSet/all>
B<TMTOWTDI!>
=head2 SQL: Update
my $update = $dbh->prepare('
UPDATE books
SET title = ?
WHERE id = ?
');
$update->execute( 'New title', $book_id );
=head2 DBIC: Update
$book->update({ title => 'New title' });
See L<DBIx::Class::Row/update>
Will not update unless value changes
=head2 SQL: Delete
my $delete = $dbh->prepare('DELETE FROM books WHERE id = ?');
$delete->execute($book_id);
=head2 DBIC: Delete
$book->delete
See L<DBIx::Class::Row/delete>
=head2 SQL: Search
my $sth = $dbh->prepare('
SELECT title,
authors.name as author_name
FROM books
WHERE books.name LIKE "%monte cristo%" AND
books.topic = "jailbreak"
');
=head2 DBIC: Search
my $book = $book_rs->search({
'me.name' => { -like => '%monte cristo%' },
'me.topic' => 'jailbreak',
})->next;
=over 1
=item See L<SQL::Abstract::Classic>, L<DBIx::Class::ResultSet/next>, and L<DBIx::Class::ResultSet/search>
=item (kinda) introspectible
=item Prettier than SQL
=back
=head2 OO Overridability
=over 1
=item Override new if you want to do validation
=item Override delete if you want to disable deletion
=item and on and on
=back
=head2 Convenience Methods
=over 1
=item L<DBIx::Class::ResultSet/find_or_create>
=item L<DBIx::Class::ResultSet/update_or_create>
=back
=head2 Non-column methods
Need a method to get a user's gravatar URL? Add a C<gravatar_url> method to the
Result class
=head2 RELATIONSHIPS
=over 1
=item L<DBIx::Class::Relationship/belongs_to>
=item L<DBIx::Class::Relationship/has_many>
=item L<DBIx::Class::Relationship/might_have>
=item L<DBIx::Class::Relationship/has_one>
=item L<DBIx::Class::Relationship/many_to_many>
=item SET AND FORGET
=back
=head1 DBIx::Class Specific Features
These things may be in other ORM's, but they are very specific, so doubtful
=head2 ->deploy
Create a database from your DBIx::Class schema.
my $schema = Frew::Schema->connect( $dsn, $user, $pass );
$schema->deploy
See L<DBIx::Class::Schema/deploy>.
See also: L<DBIx::Class::DeploymentHandler>
=head2 Schema::Loader
Create a DBIx::Class schema from your database.
package Frew::Schema;
use strict;
use warnings;
use base 'DBIx::Class::Schema::Loader';
__PACKAGE__->loader_options({
naming => 'v7',
debug => $ENV{DBIC_TRACE},
});
1;
# elsewhere...
my $schema = Frew::Schema->connect( $dsn, $user, $pass );
See L<DBIx::Class::Schema::Loader> and L<DBIx::Class::Schema::Loader::Base/CONSTRUCTOR OPTIONS>.
=head2 Populate
Made for inserting lots of rows very quickly into database
$schema->populate([ Users =>
[qw( username password )],
[qw( frew >=4char$ )],
[qw( ... )],
[qw( ... )],
);
See L<DBIx::Class::Schema/populate>
I use populate L<here|http://blog.afoolishmanifesto.com/archives/1255> to export our whole
(200M~) db to SQLite
=head2 Multicreate
Create an object and its related objects all at once
$schema->resultset('Author')->create({
name => 'Stephen King',
books => [{ title => 'The Dark Tower' }],
address => {
street => '123 Turtle Back Lane',
state => { abbreviation => 'ME' },
city => { name => 'Lowell' },
},
});
See L<DBIx::Class::ResultSet/create>
=over 1
=item books is a has_many
=item address is a belongs_to which in turn belongs to state and city each
=item for this to work right state and city must mark abbreviation and name as unique
=back
=head2 Extensible
DBIx::Class helped pioneer fast MI in Perl 5 with Class::C3, so it is made to
allow extensions to nearly every part of it.
=head2 Extensibility example: DBIx::Class::Helpers
=over 1
=item L<DBIx::Class::Helper::ResultSet::IgnoreWantarray>
=item L<DBIx::Class::Helper::ResultSet::Random>
=item L<DBIx::Class::Helper::ResultSet::SetOperations>
=item L<DBIx::Class::Helper::Row::JoinTable>
=item L<DBIx::Class::Helper::Row::NumifyGet>
=item L<DBIx::Class::Helper::Row::SubClass>
=item L<DBIx::Class::Helper::Row::ToJSON>
=item L<DBIx::Class::Helper::Row::StorageValues>
=item L<DBIx::Class::Helper::Row::OnColumnChange>
=back
=head2 Extensibility example: DBIx::Class::TimeStamp
=over 1
=item See L<DBIx::Class::TimeStamp>
=item Cross DB
=item set_on_create
=item set_on_update
=back
=head2 Extensibility example: Kioku
=over 1
=item See L<DBIx::Class::Schema::KiokuDB>
=item Kioku is the new hotness
=item Mix RDBMS with Object DB
=back
=head2 Result vs ResultSet
=over 1
=item Result == Row
=item ResultSet == Query Plan
=over 1
=item Internal Join Optimizer for all DB's (!!!)
=back
=item (less important but...)
=item ResultSource == Queryable collection of rows (Table, View, etc)
=item Storage == Database
=item Schema == associates a set of ResultSources with a Storage
=back
=head2 ResultSet methods
package MyApp::Schema::ResultSet::Book;
use strict;
use warnings;
use base 'DBIx::Class::ResultSet';
sub good {
my $self = shift;
$self->search({
$self->current_source_alias . '.rating' => { '>=' => 4 }
})
};
sub cheap {
my $self = shift;
$self->search({
$self->current_source_alias . '.price' => { '<=' => 5}
})
};
# ...
1;
See L<DBIx::Class::Manual::Cookbook/Predefined searches>
=over 1
=item All searches should be ResultSet methods
=item Name has obvious meaning
=item L<DBIx::Class::ResultSet/current_source_alias> helps things to work no matter what
=back
=head2 ResultSet method in Action
$schema->resultset('Book')->good
=head2 ResultSet Chaining
$schema->resultset('Book')
->good
->cheap
->recent
=head2 search_related
my $score = $schema->resultset('User')
->search({'me.userid' => 'frew'})
->related_resultset('access')
->related_resultset('mgmt')
->related_resultset('orders')
->telephone
->search_related( shops => {
'shops.datecompleted' => {
-between => ['2009-10-01','2009-10-08']
}
})->completed
->related_resultset('rpt_score')
->search(undef, { rows => 1})
->get_column('raw_scores')
->next;
The SQL that this produces (with placeholders filled in for clarity's sake)
on our system (Microsoft SQL) is:
SELECT raw_scores
FROM (
SELECT raw_scores, ROW_NUMBER() OVER (
ORDER BY (
SELECT (1)
)
) AS rno__row__index
FROM (
SELECT rpt_score.raw_scores
FROM users me
JOIN access access
ON access.userid = me.userid
JOIN mgmt mgmt
ON mgmt.mgmtid = access.mgmtid
JOIN [order] orders
ON orders.mgmtid = mgmt.mgmtid
JOIN shop shops
ON shops.orderno = orders.orderno
JOIN rpt_scores rpt_score
ON rpt_score.shopno = shops.shopno
WHERE (
datecompleted IS NOT NULL AND
(
(shops.datecompleted BETWEEN '2009-10-01' AND '2009-10-08') AND
(type = '1' AND me.userid = 'frew')
)
)
) rpt_score
) rpt_score
WHERE rno__row__index BETWEEN 1 AND 1
See: L<DBIx::Class::ResultSet/related_resultset>,
L<DBIx::Class::ResultSet/search_related>, and
L<DBIx::Class::ResultSet/get_column>.
=head2 bonus rel methods
my $book = $author->create_related(
books => {
title => 'Another Discworld book',
}
);
my $book2 = $pratchett->add_to_books({
title => 'MOAR Discworld book',
});
See L<DBIx::Class::Relationship::Base/create_related> and L<DBIx::Class::Relationship::Base/add_to_$rel>
Note that it automatically fills in foreign key for you
=head2 Excellent Transaction Support
$schema->txn_do(sub {
...
});
$schema->txn_begin; # <-- low level
# ...
$schema->txn_commit;
See L<DBIx::Class::Schema/txn_do>, L<DBIx::Class::Schema/txn_begin>,
and L<DBIx::Class::Schema/txn_commit>.
=head2 InflateColumn
package Frew::Schema::Result::Book;
use strict;
use warnings;
use base 'DBIx::Class::Core';
use DateTime::Format::MySQL;
# Result code here
__PACKAGE__->load_components('InflateColumn');
__PACKAGE__->inflate_column(
date_published => {
inflate => sub { DateTime::Format::MySQL->parse_date( shift ) },
deflate => sub { shift->ymd },
},
);
See L<DBIx::Class::InflateColumn>, L<DBIx::Class::InflateColumn/inflate_column>, and
L<DBIx::Class::InflateColumn::DateTime>.
=head2 InflateColumn: deflation
$book->date_published(DateTime->now);
$book->update;
=head2 InflateColumn: inflation
say $book->date_published->month_abbr; # Nov
=head2 FilterColumn
package Frew::Schema::Result::Book;
use strict;
use warnings;
use base 'DBIx::Class::Core';
# Result code here
__PACKAGE__->load_components('FilterColumn');
__PACKAGE__->filter_column(
length => {
to_storage => 'to_metric',
from_storage => 'to_imperial',
},
);
sub to_metric { $_[1] * .305 }
sub to_imperial { $_[1] * 3.28 }
See L<DBIx::Class::FilterColumn> and L<DBIx::Class::FilterColumn/filter_column>
=head2 ResultSetColumn
my $rsc = $schema->resultset('Book')->get_column('price');
$rsc->first;
$rsc->all;
$rsc->min;
$rsc->max;
$rsc->sum;
See L<DBIx::Class::ResultSetColumn>
=head2 Aggregates
my @res = $rs->search(undef, {
select => [
'price',
'genre',
{ max => price },
{ avg => price },
],
as => [
qw(price genre max_price avg_price)
],
group_by => [qw(price genre)],
});
for (@res) {
say $_->price . ' ' . $_->genre;
say $_->get_column('max_price');
say $_->get_column('avg_price');
}
See L<DBIx::Class::ResultSet/select>, L<DBIx::Class::ResultSet/as>, and
L<DBIx::Class::ResultSet/group_by>
=over 1
=item Careful, get_column can basically mean B<three> things
=item private in which case you should use an accessor
=item public for what there is no accessor for
=item public for get resultset column (prev example)
=back
=head2 HRI
$rs->search(undef, {
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
});
See L<DBIx::Class::ResultSet/result_class> and L<DBIx::Class::ResultClass::HashRefInflator>.
=over 1
=item Easy on memory
=item Mega fast
=item Great for quick debugging
=item Great for performance tuning (we went from 2m to < 3s)
=back
=head2 Subquery Support
my $inner_query = $schema->resultset('Artist')
->search({
name => [ 'Billy Joel', 'Brittany Spears' ],
})->get_column('id')->as_query;
my $rs = $schema->resultset('CD')->search({
artist_id => { -in => $inner_query },
});
See L<DBIx::Class::Manual::Cookbook/Subqueries>
=head2 Bare SQL w/ Placeholders
$rs->update({
# !!! SQL INJECTION VECTOR
price => \"price + $inc", # DON'T DO THIS
});
Better:
$rs->update({
price => \['price + ?', [inc => $inc]],
});
See L<SQL::Abstract::Classic/Literal SQL with placeholders and bind values (subqueries)>
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,167 @@
=head1 NAME
DBIx::Class::Manual::Glossary - Clarification of terms used.
=head1 INTRODUCTION
This document lists various terms used in DBIx::Class and attempts to
explain them.
=head1 DBIx::Class TERMS
=head2 DB schema
Refers to a single physical schema within an RDBMS. Synonymous with the terms
'database', for MySQL; and 'schema', for most other RDBMS(s).
In other words, it's the 'xyz' _thing_ you're connecting to when using any of
the following L<DSN|DBI/connect>(s):
dbi:DriverName:xyz@hostname:port
dbi:DriverName:database=xyz;host=hostname;port=port
=head2 Inflation
The act of turning database row data into objects in
language-space. DBIx::Class result classes can be set up to inflate
your data into perl objects which more usefully represent their
contents. For example: L<DBIx::Class::InflateColumn::DateTime> for
datetime or timestamp column data.
See also L<DBIx::Class::InflateColumn>.
=head2 Deflation
The opposite of L</Inflation>. Existing perl objects that represent
column values can be passed to DBIx::Class methods to store into the
database. For example a L<DateTime> object can be automatically
deflated into a datetime string for insertion.
See L<DBIx::Class::InflateColumn> and other modules in that namespace.
=head2 ORM
Object-relational mapping, or Object-relationship modelling. Either
way it's a method of mapping the contents of database tables (rows),
to objects in programming-language-space. DBIx::Class is an ORM.
=head2 Relationship
In DBIx::Class a relationship defines the connection between exactly
two tables. The relationship condition lists the columns in each table
that contain the same values. It is used to output an SQL JOIN
condition between the tables.
=head2 Relationship bridge
A relationship bridge, such as C<many_to_many> defines an accessor to
retrieve row contents across multiple relationships.
The difference between a bridge and a relationship is, that the bridge
cannot be used to C<join> tables in a C<search>, instead its component
relationships must be used.
=head2 Schema
A Schema object represents your entire table collection, plus the
connection to the database. You can create one or more schema objects,
connected to various databases, with various users, using the same set
of table L</Result Class> definitions.
At least one L<DBIx::Class::Schema> class is needed per database.
=head2 Result Class
A Result class defines both a source of data (usually one per table),
and the methods that will be available in the L</Result> objects
created using that source.
One Result class is needed per data source (table, view, query) used
in your application, they should inherit from L<DBIx::Class::Core>.
See also: L<DBIx::Class::Manual::ResultClass>
=head2 ResultSource
ResultSource objects represent the source of your data, these are
sometimes (incorrectly) called table objects.
ResultSources do not need to be directly created, a ResultSource
instance is created for each L</Result Class> in your L</Schema>, by
the proxied methods C<table> and C<add_columns>.
See also: L<DBIx::Class::ResultSource/METHODS>
=head2 ResultSet
This is an object representing a set of conditions to filter data. It
can either be an entire table, or the results of a query. The actual
data is not held in the ResultSet, it is only a description of how to
fetch the data.
See also: L<DBIx::Class::ResultSet/METHODS>
=head2 Result
Result objects contain your actual data. They are returned from
ResultSet objects. These are sometimes (incorrectly) called
row objects, including older versions of the DBIC documentation.
See also: L<DBIx::Class::Manual::ResultClass>
=head2 Row
See Result.
=head2 Object
See Result.
=head2 Record
See Result.
=head2 prefetch
Similar to a join, except the related result objects are fetched and
cached for future use, instead of used directly from the ResultSet. This
allows you to jump to different relationships within a Result without
worrying about generating a ton of extra SELECT statements.
=head1 SQL TERMS
=head2 CRUD
Create, Read, Update, Delete. A general concept of something that can
do all four operations (INSERT, SELECT, UPDATE, DELETE), usually at a
row-level.
=head2 Join
This is an SQL keyword, it is used to link multiple tables in one SQL
statement. This enables us to fetch data from more than one table at
once, or filter data based on content in another table, without having
to issue multiple SQL queries.
=head2 Normalisation
A normalised database is a sane database. Each table contains only
data belonging to one concept, related tables refer to the key field
or fields of each other. Some links to webpages about normalisation
can be found in L<the FAQ|DBIx::Class::Manual::FAQ>.
=head2 Related data
In SQL, related data actually refers to data that are normalised into
the same table. (Yes. DBIC does mis-use this term.)
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,483 @@
=head1 NAME
DBIx::Class::Manual::Intro - Introduction to DBIx::Class
=head1 INTRODUCTION
You're bored with SQL, and want a native Perl interface for your database? Or
you've been doing this for a while with L<Class::DBI>, and think there's a
better way? You've come to the right place.
=head1 THE DBIx::Class WAY
Here are a few simple tips that will help you get your bearings with
DBIx::Class.
=head2 Tables become Result classes
DBIx::Class needs to know what your Table structure looks like. You
do that by defining Result classes. Result classes are defined by
calling methods proxied to L<DBIx::Class::ResultSource>. Each Result
class defines one Table, which defines the Columns it has, along with
any Relationships it has to other tables. (And oh, so much more
besides) The important thing to understand:
A Result class == Table
(most of the time, but just bear with my simplification)
=head2 It's all about the ResultSet
So, we've got some ResultSources defined. Now, we want to actually use those
definitions to help us translate the queries we need into handy perl objects!
Let's say we defined a ResultSource for an "album" table with three columns:
"albumid", "artist", and "title". Any time we want to query this table, we'll
be creating a L<DBIx::Class::ResultSet> from its ResultSource. For example, the
results of:
SELECT albumid, artist, title FROM album;
Would be retrieved by creating a ResultSet object from the album table's
ResultSource, likely by using the "search" method.
DBIx::Class doesn't limit you to creating only simple ResultSets -- if you
wanted to do something like:
SELECT title FROM album GROUP BY title;
You could easily achieve it.
The important thing to understand:
Any time you would reach for a SQL query in DBI, you are
creating a DBIx::Class::ResultSet.
=head2 Search is like "prepare"
DBIx::Class tends to wait until it absolutely must fetch information from the
database. If you are returning a ResultSet, the query won't execute until you
use a method that wants to access the data. (Such as "next", or "first")
The important thing to understand:
Setting up a ResultSet does not execute the query; retrieving
the data does.
=head2 Search results are returned as Rows
Rows of the search from the database are blessed into
L<Result|DBIx::Class::Manual::ResultClass> objects.
=head1 SETTING UP DBIx::Class
Let's look at how you can set and use your first native L<DBIx::Class> tree.
First we'll see how you can set up your classes yourself. If you want them to
be auto-discovered, just skip to the L<next section|/Using
DBIx::Class::Schema::Loader>, which shows you how to use
L<DBIx::Class::Schema::Loader>.
=head2 Setting it up manually
First, you should create your base schema class, which inherits from
L<DBIx::Class::Schema>:
package My::Schema;
use base qw/DBIx::Class::Schema/;
In this class you load your result_source ("table", "model") classes, which we
will define later, using the load_namespaces() method:
# load My::Schema::Result::* and their resultset classes
__PACKAGE__->load_namespaces();
By default this loads all the Result (Row) classes in the
My::Schema::Result:: namespace, and also any resultset classes in the
My::Schema::ResultSet:: namespace (if missing, the resultsets are
defaulted to be DBIx::Class::ResultSet objects). You can change the
result and resultset namespaces by using options to the
L<DBIx::Class::Schema/load_namespaces> call.
It is also possible to do the same things manually by calling
C<load_classes> for the Row classes and defining in those classes any
required resultset classes.
Next, create each of the classes you want to load as specified above:
package My::Schema::Result::Album;
use base qw/DBIx::Class::Core/;
Load any additional components you may need with the load_components() method,
and provide component configuration if required. For example, if you want
automatic row ordering:
__PACKAGE__->load_components(qw/ Ordered /);
__PACKAGE__->position_column('rank');
Ordered will refer to a field called 'position' unless otherwise directed. Here you are defining
the ordering field to be named 'rank'. (NOTE: Insert errors may occur if you use the Ordered
component, but have not defined a position column or have a 'position' field in your row.)
Set the table for your class:
__PACKAGE__->table('album');
Add columns to your class:
__PACKAGE__->add_columns(qw/ albumid artist title rank /);
Each column can also be set up with its own accessor, data_type and other pieces
of information that it may be useful to have -- just pass C<add_columns> a hash:
__PACKAGE__->add_columns(albumid =>
{ accessor => 'album',
data_type => 'integer',
size => 16,
is_nullable => 0,
is_auto_increment => 1,
},
artist =>
{ data_type => 'integer',
size => 16,
is_nullable => 0,
},
title =>
{ data_type => 'varchar',
size => 256,
is_nullable => 0,
},
rank =>
{ data_type => 'integer',
size => 16,
is_nullable => 0,
default_value => 0,
}
);
DBIx::Class doesn't directly use most of this data yet, but various related
modules such as L<HTML::FormHandler::Model::DBIC> make use of it.
Also it allows you to create your database tables from your Schema,
instead of the other way around.
See L<DBIx::Class::Schema/deploy> for details.
See L<DBIx::Class::ResultSource> for more details of the possible column
attributes.
Accessors are created for each column automatically, so My::Schema::Result::Album will
have albumid() (or album(), when using the accessor), artist() and title()
methods.
Define a primary key for your class:
__PACKAGE__->set_primary_key('albumid');
If you have a multi-column primary key, just pass a list instead:
__PACKAGE__->set_primary_key( qw/ albumid artistid / );
Define this class' relationships with other classes using either C<belongs_to>
to describe a column which contains an ID of another Table, or C<has_many> to
make a predefined accessor for fetching objects that contain this Table's
foreign key:
# in My::Schema::Result::Artist
__PACKAGE__->has_many('albums', 'My::Schema::Result::Album', 'artist');
See L<DBIx::Class::Relationship> for more information about the various types of
available relationships and how you can design your own.
=head2 Using DBIx::Class::Schema::Loader
This module (L<DBIx::Class::Schema::Loader>) is an external module, and not part
of the L<DBIx::Class> distribution. It inspects your database, and automatically
creates classes for all the tables in your schema.
The simplest way to use it is via the L<dbicdump> script from the
L<DBIx::Class::Schema::Loader> distribution. For example:
$ dbicdump -o dump_directory=./lib \
-o components='["InflateColumn::DateTime"]' \
MyApp::Schema dbi:mysql:mydb user pass
If you have a mixed-case database, use the C<preserve_case> option, e.g.:
$ dbicdump -o dump_directory=./lib -o preserve_case=1 \
-o components='["InflateColumn::DateTime"]' \
MyApp::Schema dbi:mysql:mydb user pass
If you are using L<Catalyst>, then you can use the helper that comes with
L<Catalyst::Model::DBIC::Schema>:
$ script/myapp_create.pl model MyModel DBIC::Schema MyApp::Schema \
create=static moniker_map='{ foo => "FOO" }' dbi:SQLite:./myapp.db \
on_connect_do='PRAGMA foreign_keys=ON' quote_char='"'
See L<Catalyst::Helper::Model::DBIC::Schema> for more information on this
helper.
See the L<DBIx::Class::Schema::Loader> and L<DBIx::Class::Schema::Loader::Base>
documentation for more information on the many loader options.
=head2 Connecting
To connect to your Schema, you need to provide the connection details or a
database handle.
=head3 Via connection details
The arguments are the same as for L<DBI/connect>:
my $schema = My::Schema->connect('dbi:SQLite:/home/me/myapp/my.db');
You can create as many different schema instances as you need. So if you have a
second database you want to access:
my $other_schema = My::Schema->connect( $dsn, $user, $password, $attrs );
Note that L<DBIx::Class::Schema> does not cache connections for you. If you use
multiple connections, you need to do this manually.
To execute some SQL statements on every connect you can add them as an option in
a special fifth argument to connect:
my $another_schema = My::Schema->connect(
$dsn,
$user,
$password,
$attrs,
{ on_connect_do => \@on_connect_sql_statments }
);
See L<DBIx::Class::Storage::DBI/connect_info> for more information about
this and other special C<connect>-time options.
=head3 Via a database handle
The supplied coderef is expected to return a single connected database handle
(e.g. a L<DBI> C<$dbh>)
my $schema = My::Schema->connect (
sub { Some::DBH::Factory->connect },
\%extra_attrs,
);
=head2 Basic usage
Once you've defined the basic classes, either manually or using
L<DBIx::Class::Schema::Loader>, you can start interacting with your database.
To access your database using your $schema object, you can fetch a
L<DBIx::Class::Manual::Glossary/"ResultSet"> representing each of your tables by
calling the C<resultset> method.
The simplest way to get a record is by primary key:
my $album = $schema->resultset('Album')->find(14);
This will run a C<SELECT> with C<albumid = 14> in the C<WHERE> clause, and
return an instance of C<My::Schema::Result::Album> that represents this row. Once you
have that row, you can access and update columns:
$album->title('Physical Graffiti');
my $title = $album->title; # $title holds 'Physical Graffiti'
If you prefer, you can use the C<set_column> and C<get_column> accessors
instead:
$album->set_column('title', 'Presence');
$title = $album->get_column('title');
Just like with L<Class::DBI>, you call C<update> to save your changes to the
database (by executing the actual C<UPDATE> statement):
$album->update;
If needed, you can throw away your local changes:
$album->discard_changes if $album->is_changed;
As you can see, C<is_changed> allows you to check if there are local changes to
your object.
=head2 Adding and removing rows
To create a new record in the database, you can use the C<create> method. It
returns an instance of C<My::Schema::Result::Album> that can be used to access the data
in the new record:
my $new_album = $schema->resultset('Album')->create({
title => 'Wish You Were Here',
artist => 'Pink Floyd'
});
Now you can add data to the new record:
$new_album->label('Capitol');
$new_album->year('1975');
$new_album->update;
Likewise, you can remove it from the database:
$new_album->delete;
You can also remove records without retrieving them first, by calling delete
directly on a ResultSet object.
# Delete all of Falco's albums
$schema->resultset('Album')->search({ artist => 'Falco' })->delete;
=head2 Finding your objects
L<DBIx::Class> provides a few different ways to retrieve data from your
database. Here's one example:
# Find all of Santana's albums
my $rs = $schema->resultset('Album')->search({ artist => 'Santana' });
In scalar context, as above, C<search> returns a L<DBIx::Class::ResultSet>
object. It can be used to peek at the first album returned by the database:
my $album = $rs->first;
print $album->title;
You can loop over the albums and update each one:
while (my $album = $rs->next) {
print $album->artist . ' - ' . $album->title;
$album->year(2001);
$album->update;
}
Or, you can update them all at once:
$rs->update({ year => 2001 });
In list context, the C<search> method returns all of the matching rows:
# Fetch immediately all of Carlos Santana's albums
my @albums = $schema->resultset('Album')->search(
{ artist => 'Carlos Santana' }
);
foreach my $album (@albums) {
print $album->artist . ' - ' . $album->title;
}
We also provide a handy shortcut for doing a C<LIKE> search:
# Find albums whose artist starts with 'Jimi'
my $rs = $schema->resultset('Album')->search_like({ artist => 'Jimi%' });
Or you can provide your own C<WHERE> clause:
# Find Peter Frampton albums from the year 1986
my $where = 'artist = ? AND year = ?';
my @bind = ( 'Peter Frampton', 1986 );
my $rs = $schema->resultset('Album')->search_literal( $where, @bind );
The preferred way to generate complex queries is to provide a
L<SQL::Abstract::Classic>-compatible construct to C<search>:
my $rs = $schema->resultset('Album')->search({
artist => { '!=', 'Janis Joplin' },
year => { '<' => 1980 },
albumid => { '-in' => [ 1, 14, 15, 65, 43 ] }
});
This results in something like the following C<WHERE> clause:
WHERE artist != 'Janis Joplin'
AND year < 1980
AND albumid IN (1, 14, 15, 65, 43)
For more examples of complex queries, see L<DBIx::Class::Manual::Cookbook>.
The search can also be modified by passing another hash with
attributes:
my @albums = My::Schema->resultset('Album')->search(
{ artist => 'Bob Marley' },
{ rows => 2, order_by => { -desc => 'year' } }
);
C<@albums> then holds the two most recent Bob Marley albums.
For more information on what you can do with a L<DBIx::Class::ResultSet>, see
L<DBIx::Class::ResultSet/METHODS>.
For a complete overview of the available attributes, see
L<DBIx::Class::ResultSet/ATTRIBUTES>.
=head1 NOTES
=head2 The Significance and Importance of Primary Keys
The concept of a L<primary key|DBIx::Class::ResultSource/set_primary_key> in
DBIx::Class warrants special discussion. The formal definition (which somewhat
resembles that of a classic RDBMS) is I<a unique constraint that is least
likely to change after initial row creation>. However this is where the
similarity ends. Any time you call a CRUD operation on a row (e.g.
L<delete|DBIx::Class::Row/delete>,
L<update|DBIx::Class::Row/update>,
L<discard_changes|DBIx::Class::Row/discard_changes>,
etc.) DBIx::Class will use the values of the
L<primary key|DBIx::Class::ResultSource/set_primary_key> columns to populate
the C<WHERE> clause necessary to accomplish the operation. This is why it is
important to declare a L<primary key|DBIx::Class::ResultSource/set_primary_key>
on all your result sources B<even if the underlying RDBMS does not have one>.
In a pinch one can always declare each row identifiable by all its columns:
__PACKAGE__->set_primary_key(__PACKAGE__->columns);
Note that DBIx::Class is smart enough to store a copy of the PK values before
any row-object changes take place, so even if you change the values of PK
columns the C<WHERE> clause will remain correct.
If you elect not to declare a C<primary key>, DBIx::Class will behave correctly
by throwing exceptions on any row operation that relies on unique identifiable
rows. If you inherited datasets with multiple identical rows in them, you can
still operate with such sets provided you only utilize
L<DBIx::Class::ResultSet> CRUD methods:
L<search|DBIx::Class::ResultSet/search>,
L<update|DBIx::Class::ResultSet/update>,
L<delete|DBIx::Class::ResultSet/delete>
For example, the following would not work (assuming C<People> does not have
a declared PK):
my $result = $schema->resultset('People')
->search({ last_name => 'Dantes' })
->next;
$result->update({ children => 2 }); # <-- exception thrown because $result isn't
# necessarily unique
So instead the following should be done:
$schema->resultset('People')
->search({ last_name => 'Dantes' })
->update({ children => 2 }); # <-- update's ALL Dantes to have children of 2
=head2 Problems on RHEL5/CentOS5
There used to be an issue with the system perl on Red Hat Enterprise
Linux 5, some versions of Fedora and derived systems. Further
information on this can be found in L<DBIx::Class::Manual::Troubleshooting>
=head1 SEE ALSO
=over 4
=item * L<DBIx::Class::Manual::Cookbook>
=back
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,286 @@
=head1 NAME
DBIx::Class::Manual::Joining - Manual on joining tables with DBIx::Class
=head1 DESCRIPTION
This document should help you to use L<DBIx::Class> if you are trying
to convert your normal SQL queries into DBIx::Class based queries, if
you use joins extensively (and also probably if you don't).
=head1 WHAT ARE JOINS
If you ended up here and you don't actually know what joins are yet,
then you should likely try the L<DBIx::Class::Manual::Intro>
instead. Skip this part if you know what joins are..
But I'll explain anyway. Assuming you have created your database in a
more or less sensible way, you will end up with several tables that
contain C<related> information. For example, you may have a table
containing information about C<CD>s, containing the CD title and its
year of publication, and another table containing all the C<Track>s
for the CDs, one track per row.
When you wish to extract information about a particular CD and all
its tracks, You can either fetch the CD row, then make another query
to fetch the tracks, or you can use a join. Compare:
SELECT ID, Title, Year FROM CD WHERE Title = 'Funky CD';
# .. Extract the ID, which is 10
SELECT Name, Artist FROM Tracks WHERE CDID = 10;
SELECT cd.ID, cd.Title, cd.Year, tracks.Name, tracks.Artist FROM CD JOIN Tracks ON CD.ID = tracks.CDID WHERE cd.Title = 'Funky CD';
So, joins are a way of extending simple select statements to include
fields from other, related, tables. There are various types of joins,
depending on which combination of the data you wish to retrieve, see
MySQL's doc on JOINs:
L<http://dev.mysql.com/doc/refman/5.0/en/join.html>.
=head1 DEFINING JOINS AND RELATIONSHIPS
In L<DBIx::Class> each relationship between two tables needs to first
be defined in the L<ResultSource|DBIx::Class::Manual::Glossary/ResultSource> for the
table. If the relationship needs to be accessed in both directions
(i.e. Fetch all tracks of a CD, and fetch the CD data for a Track),
then it needs to be defined for both tables.
For the CDs/Tracks example, that means writing, in C<MySchema::CD>:
MySchema::CD->has_many('tracks', 'MySchema::Tracks');
And in C<MySchema::Tracks>:
MySchema::Tracks->belongs_to('cd', 'MySchema::CD', 'CDID');
There are several other types of relationships, they are more
comprehensively described in L<DBIx::Class::Relationship>.
=head1 USING JOINS
Once you have defined all your relationships, using them in actual
joins is fairly simple. The type of relationship that you chose
e.g. C<has_many>, already indicates what sort of join will be
performed. C<has_many> produces a C<LEFT JOIN> for example, which will
fetch all the rows on the left side, whether there are matching rows
on the right (table being joined to), or not. You can force other
types of joins in your relationship, see the
L<DBIx::Class::Relationship> docs.
When performing either a L<search|DBIx::Class::ResultSet/search> or a
L<find|DBIx::Class::ResultSet/find> operation, you can specify which
C<relations> to also refine your results based on, using the
L<join|DBIx::Class::ResultSet/join> attribute, like this:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD',
'tracks.Name' => { like => 'T%' }
},
{ join => 'tracks',
order_by => ['tracks.id'],
}
);
If you don't recognise most of this syntax, you should probably go
read L<DBIx::Class::ResultSet/search> and
L<DBIx::Class::ResultSet/ATTRIBUTES>, but here's a quick break down:
The first argument to search is a hashref of the WHERE attributes, in
this case a restriction on the Title column in the CD table, and a
restriction on the name of the track in the Tracks table, but ONLY for
tracks actually related to the chosen CD(s). The second argument is a
hashref of attributes to the search, the results will be returned
sorted by the C<id> of the related tracks.
The special 'join' attribute specifies which C<relationships> to
include in the query. The distinction between C<relationships> and
C<tables> is important here, only the C<relationship> names are valid.
This slightly nonsense example will produce SQL similar to:
SELECT cd.ID, cd.Title, cd.Year FROM CD cd JOIN Tracks tracks ON cd.ID = tracks.CDID WHERE cd.Title = 'Funky CD' AND tracks.Name LIKE 'T%' ORDER BY 'tracks.id';
=head1 FETCHING RELATED DATA
Another common use for joining to related tables, is to fetch the data
from both tables in one query, preventing extra round-trips to the
database. See the example above in L</WHAT ARE JOINS>.
Three techniques are described here. Of the three, only the
C<prefetch> technique will deal sanely with fetching related objects
over a C<has_many> relation. The others work fine for 1 to 1 type
relationships.
=head2 Whole related objects
To fetch entire related objects, e.g. CDs and all Track data, use the
'prefetch' attribute:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD',
},
{ prefetch => 'tracks',
order_by => ['tracks.id'],
}
);
This will produce SQL similar to the following:
SELECT cd.ID, cd.Title, cd.Year, tracks.id, tracks.Name, tracks.Artist FROM CD JOIN Tracks ON CD.ID = tracks.CDID WHERE cd.Title = 'Funky CD' ORDER BY 'tracks.id';
The syntax of 'prefetch' is the same as 'join' and implies the
joining, so there is no need to use both together.
=head2 Subset of related fields
To fetch a subset or the related fields, the '+select' and '+as'
attributes can be used. For example, if the CD data is required and
just the track name from the Tracks table:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD',
},
{ join => 'tracks',
'+select' => ['tracks.Name'],
'+as' => ['track_name'],
order_by => ['tracks.id'],
}
);
Which will produce the query:
SELECT cd.ID, cd.Title, cd.Year, tracks.Name FROM CD JOIN Tracks ON CD.ID = tracks.CDID WHERE cd.Title = 'Funky CD' ORDER BY 'tracks.id';
Note that the '+as' does not produce an SQL 'AS' keyword in the
output, see the L<DBIx::Class::Manual::FAQ> for an explanation.
This type of column restriction has a downside, the returned $result
object will have no 'track_name' accessor:
while(my $result = $search_rs->next) {
print $result->track_name; ## ERROR
}
Instead C<get_column> must be used:
while(my $result = $search_rs->next) {
print $result->get_column('track_name'); ## WORKS
}
=head2 Incomplete related objects
In rare circumstances, you may also wish to fetch related data as
incomplete objects. The usual reason to do is when the related table
has a very large field you don't need for the current data
output. This is better solved by storing that field in a separate
table which you only join to when needed.
To fetch an incomplete related object, supply the dotted notation to the '+as' attribute:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD',
},
{ join => 'tracks',
'+select' => ['tracks.Name'],
'+as' => ['tracks.Name'],
order_by => ['tracks.id'],
}
);
Which will produce same query as above;
SELECT cd.ID, cd.Title, cd.Year, tracks.Name FROM CD JOIN Tracks ON CD.ID = tracks.CDID WHERE cd.Title = 'Funky CD' ORDER BY 'tracks.id';
Now you can access the result using the relationship accessor:
while(my $result = $search_rs->next) {
print $result->tracks->name; ## WORKS
}
However, this will produce broken objects. If the tracks id column is
not fetched, the object will not be usable for any operation other
than reading its data. Use the L</Whole related objects> method as
much as possible to avoid confusion in your code later.
Broken means: Update will not work. Fetching other related objects
will not work. Deleting the object will not work.
=head1 COMPLEX JOINS AND STUFF
=head2 Across multiple relations
For simplicity in the example above, the C<Artist> was shown as a
simple text field in the C<Tracks> table, in reality, you'll want to
have the artists in their own table as well, thus to fetch the
complete set of data we'll need to join to the Artist table too.
In C<MySchema::Tracks>:
MySchema::Tracks->belongs_to('artist', 'MySchema::Artist', 'ArtistID');
The search:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD' },
{ join => { 'tracks' => 'artist' },
}
);
Which is:
SELECT me.ID, me.Title, me.Year FROM CD me JOIN Tracks tracks ON CD.ID = tracks.CDID JOIN Artists artist ON tracks.ArtistID = artist.ID WHERE me.Title = 'Funky CD';
To perform joins using relations of the tables you are joining to, use
a hashref to indicate the join depth. This can theoretically go as
deep as you like (warning: contrived examples!):
join => { room => { table => 'leg' } }
To join two relations at the same level, use an arrayref instead:
join => { room => [ 'chair', 'table' ] }
Or combine the two:
join => { room => [ 'chair', { table => 'leg' } ] }
=head2 Table aliases
As an aside to all the discussion on joins, note that L<DBIx::Class>
uses the C<relation names> as table aliases. This is important when
you need to add grouping or ordering to your queries:
$schema->resultset('CD')->search(
{ 'Title' => 'Funky CD' },
{ join => { 'tracks' => 'artist' },
order_by => [ 'tracks.Name', 'artist.Artist' ],
}
);
SELECT me.ID, me.Title, me.Year FROM CD me JOIN Tracks tracks ON CD.ID = tracks.CDID JOIN Artists artist ON tracks.ArtistID = artist.ID WHERE me.Title = 'Funky CD' ORDER BY tracks.Name, artist.Artist;
This is essential if any of your tables have columns with the same names.
Note that the table of the resultsource the search was performed on, is always aliased to C<me>.
=head2 Joining to the same table twice
There is no magic to this, just do it. The table aliases will
automatically be numbered:
join => [ 'room', 'room' ]
The aliases are: C<room> and C<room_2>.
=cut
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,205 @@
=head1 NAME
DBIx::Class::Manual::QuickStart - up and running with DBIC in 10 minutes
=head1 DESCRIPTION
This document shows the minimum amount of code to make you a productive DBIC
user. It requires you to be familiar with just the basics of database
programming (what database tables, rows and columns are) and the basics of
Perl object-oriented programming (calling methods on an object instance).
It also helps if you already know a bit of SQL and how to connect to a
database through DBI.
Follow along with the example database shipping with this distribution,
see directory F<examples/Schema>. This database is also used through-out the
rest of the documentation.
=head2 Preparation
First, install DBIx::Class like you do with any other CPAN distribution.
See L<http://www.cpan.org/modules/INSTALL.html> and L<perlmodinstall>.
Then open the distribution in your shell and change to the subdirectory
mentioned earlier, the next command will download and unpack it:
$ perl -mCPAN -e'CPAN::Shell->look("DBIx::Class")'
DBIx-Class$ cd examples/Schema
Inspect the database:
DBIx-Class/examples/Schema$ sqlite3 db/example.db .dump
You can also use a GUI database browser such as
L<SQLite Manager|https://addons.mozilla.org/firefox/addon/sqlite-manager>.
Have a look at the schema classes files in the subdirectory F<MyApp>. The
C<MyApp::Schema> class is the entry point for loading the other classes and
interacting with the database through DBIC and the C<Result> classes correspond
to the tables in the database. L<DBIx::Class::Manual::Example> shows how to
write all that Perl code. That is almost never necessary, though. Instead use
L<dbicdump> (part of the distribution L<DBIx::Class::Schema::Loader>) to
automatically create schema classes files from an existing database. The
chapter L</"Resetting the database"> below shows an example invocation.
=head2 Connecting to the database
A L<schema|DBIx::Class::Manual::Glossary/Schema> object represents the database.
use MyApp::Schema qw();
my $schema = MyApp::Schema->connect('dbi:SQLite:db/example.db');
The first four arguments are the same as for L<DBI/connect>.
=head2 Working with data
Almost all actions go through a
L<resultset|DBIx::Class::Manual::Glossary/ResultSet> object.
=head3 Adding data
Via intermediate result objects:
my $artist_ma = $schema->resultset('Artist')->create({
name => 'Massive Attack',
});
my $cd_mezz = $artist_ma->create_related(cds => {
title => 'Mezzanine',
});
for ('Angel', 'Teardrop') {
$cd_mezz->create_related(tracks => {
title => $_
});
}
Via relation accessors:
$schema->resultset('Artist')->create({
name => 'Metallica',
cds => [
{
title => q{Kill 'Em All},
tracks => [
{ title => 'Jump in the Fire' },
{ title => 'Whiplash' },
],
},
{
title => 'ReLoad',
tracks => [
{ title => 'The Memory Remains' },
{ title => 'The Unforgiven II' },
{ title => 'Fuel' },
],
},
],
});
Columns that are not named are filled with default values. The value C<undef>
acts as a C<NULL> in the database.
See the chapter L</"Introspecting the schema classes"> below to find out where
the non-obvious source name strings such as C<Artist> and accessors such as
C<cds> and C<tracks> come from.
Set the environment variable C<DBI_TRACE='1|SQL'> to see the generated queries.
=head3 Retrieving data
Set up a condition.
my $artists_starting_with_m = $schema->resultset('Artist')->search(
{
name => { like => 'M%' }
}
);
Iterate over result objects of class C<MyApp::Schema::Result::Artist>.
L<Result|DBIx::Class::Manual::Glossary/Result> objects represent a row and
automatically get accessors for their column names.
for my $artist ($artists_starting_with_m->all) {
say $artist->name;
}
=head3 Changing data
Change the release year of all CDs titled I<ReLoad>.
$schema->resultset('Cd')->search(
{
title => 'ReLoad',
}
)->update_all(
{
year => 1997,
}
);
=head3 Removing data
Removes all tracks titled I<Fuel> regardless of which CD the belong to.
$schema->resultset('Track')->search(
{
title => 'Fuel',
}
)->delete_all;
=head2 Introspecting the schema classes
This is useful for getting a feel for the naming of things in a REPL or during
explorative programming.
From the root to the details:
$schema->sources; # returns qw(Cd Track Artist)
$schema->source('Cd')->columns; # returns qw(cdid artist title year)
$schema->source('Cd')->relationships; # returns qw(artist tracks)
From a detail to the root:
$some_result->result_source; # returns appropriate source
$some_resultset->result_source;
$some_resultsource->schema; # returns appropriate schema
=head2 Resetting the database
# delete database file
DBIx-Class/examples/Schema$ rm -f db/example.db
# create database and set up tables from definition
DBIx-Class/examples/Schema$ sqlite3 db/example.db < db/example.sql
# fill them with data
DBIx-Class/examples/Schema$ perl ./insertdb.pl
# delete the schema classes files
DBIx-Class/examples/Schema$ rm -rf MyApp
# recreate schema classes files from database file
DBIx-Class/examples/Schema$ dbicdump \
-o dump_directory=. MyApp::Schema dbi:SQLite:db/example.db
=head2 Where to go next
If you want to exercise what you learned with a more complicated schema,
load L<Northwind|http://code.google.com/p/northwindextended/> into your
database.
If you want to transfer your existing SQL knowledge, read
L<DBIx::Class::Manual::SQLHackers>.
Continue with L<DBIx::Class::Tutorial> and
L<DBIx::Class/"WHERE TO START READING">.
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,191 @@
=head1 NAME
DBIx::Class::Manual::Reading - How to read and write DBIx::Class POD.
=head1 DESCRIPTION
This doc should help users to understand how the examples and
documentation found in the L<DBIx::Class> distribution can be
interpreted.
Writers of DBIx::Class POD should also check here to make sure their
additions are consistent with the rest of the documentation.
=head1 METHODS
Methods should be documented in the files which also contain the code
for the method, or that file should be hidden from PAUSE completely,
in which case the methods are documented in the file which loads
it. Methods may also be documented and referred to in files
representing the major objects or components on which they can be
called.
For example, L<DBIx::Class::Relationship> documents the methods
actually coded in the helper relationship classes like
DBIx::Class::Relationship::BelongsTo. The BelongsTo file itself is
hidden from PAUSE as it has no documentation. The accessors created by
relationships should be mentioned in L<DBIx::Class::Row>, the major
object that they will be called on.
=head2 Method documentation
=over
=item *
Each method starts with a "head2" statement of its name.
Just the plain method name, not an example of how to call it, or a link.
This is to ensure easy linking to method documentation from other POD.
=item *
The header is followed by a two-item list. This contains a description
of the arguments the method is expected to take, and an indication of
what the method returns.
The first item provides a list of all possible values for the
arguments of the method in order, separated by C<, >, preceded by the
text "Arguments: "
Example (for the belongs_to relationship):
=item Arguments: $accessor_name, $related_class, $fk_column|\%cond|\@cond?, \%attr?
The following possible argument sigils can be shown:
=over
=item *
$var - A scalar (string or numeric) variable.
=item *
\%var - A variable containing reference to a hash.
=item *
\@var - A variable containing a reference to an array.
=item *
\$var - A variable containing a reference to a scalar variable.
=item *
%var - A hashref variable (list of key/value pairs) - rarely used in DBIx::Class.
Reading an argument as a hash variable will consume all subsequent
method arguments, use with caution.
=item *
@var - An array variable (list of values).
Reading an argument as a array variable will consume all subsequent
method arguments, use with caution.
=item *
L<$obj|DBIx::Class> - Reference to the source class or object definition
All arguments and return values should provide a link to the object's
class documentation or definition, even if it's the same class as the current
documentation. For example:
## Correct, if stated within DBIx::Class::ResultSet
L<$resultset|/new>
## Correct, if stated outside DBIx::Class::ResultSet
L<$resultset|DBIx::Class::ResultSet>
=item *
? - Optional, should be placed after the argument type and name.
## Correct
\%myhashref|\@myarrayref?
## Wrong
\%myhashref?|\@myarrayref
Applies to the entire argument.
Optional arguments can be left out of method calls, unless the caller
needs to pass in any of the following arguments. In which case the
caller should pass C<undef> in place of the missing argument.
=item *
| - Alternate argument content types.
At least one of these must be supplied unless the argument is also
marked optional.
=back
The second item starts with the text "Return Value:". The remainder of
the line is either the text "not defined" or a variable with a descriptive
name.
## Good examples
=item Return Value: not defined
=item Return Value: L<$schema|DBIx::Class::Schema>
=item Return Value: $classname
## Bad examples
=item Return Value: The names
"not defined" means the method does not deliberately return a value, and
the caller should not use or rely on anything it does return. (Perl
functions always return something, usually the result of the last code
statement, if there is no explicit return statement.) This is different
than specifying "undef", which means that it explicitly returns undef,
though usually this is used an alternate return (like C<$obj | undef>).
=item *
The argument/return list is followed by a single paragraph describing what
the method does.
=item *
The description paragraph is followed by another list. Each item in
the list explains one of the possible argument/type combinations.
This list may be omitted if the author feels that the variable names are
self-explanatory enough to not require it. Use best judgement.
=item *
The argument/return list is followed by some examples of how to use the
method, using its various types of arguments.
The examples can also include ways to use the results if
applicable. For instance, if the documentation is for a relationship
type, the examples can include how to call the resulting relation
accessor, how to use the relation name in a search and so on.
If some of the examples assume default values, these should be shown
with and without the actual arguments, with hints about the equivalent
calls.
The example should be followed by one or more paragraphs explaining
what it does.
Examples and explaining paragraphs can be repeated as necessary.
=back
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,103 @@
=for comment POD_DERIVED_INDEX_GENERATED
The following documentation is automatically generated. Please do not edit
this file, but rather the original, inline with DBIx::Class::Manual::ResultClass
at lib/DBIx/Class/Manual/ResultClass.pod
(on the system that originally ran this).
If you do edit this file, and don't want your changes to be removed, make
sure you change the first line.
=cut
=head1 NAME
DBIx::Class::Manual::ResultClass - Representing a single result (row) from
a DB query
=head1 SYNOPSIS
package My::Schema::Result::Track;
use parent 'DBIx::Class::Core';
__PACKAGE__->table('tracks');
__PACKAGE__->add_columns({
id => {
data_type => 'int',
is_auto_increment => 1,
},
cd_id => {
data_type => 'int',
},
title => {
data_type => 'varchar',
size => 50,
},
rank => {
data_type => 'int',
is_nullable => 1,
},
});
__PACKAGE__->set_primary_key('id');
__PACKAGE__->add_unique_constraint(u_title => ['cd_id', 'title']);
=head1 DESCRIPTION
In L<DBIx::Class>, a user normally receives query results as instances of a
certain C<Result Class>, depending on the main query source. Besides being
the primary "toolset" for interaction with your data, a C<Result Class> also
serves to establish source metadata, which is then used during initialization
of your L<DBIx::Class::Schema> instance.
Because of these multiple seemingly conflicting purposes, it is hard to
aggregate the documentation of various methods available on a typical
C<Result Class>. This document serves as a general overview of C<Result Class>
declaration best practices, and offers an index of the available methods
(and the Components/Roles which provide them).
=head1 INHERITED METHODS
=over 4
=item L<DBIx::Class::Relationship>
L<has_many|DBIx::Class::Relationship/has_many>, L<has_one|DBIx::Class::Relationship/has_one>, L<might_have|DBIx::Class::Relationship/might_have>, L<belongs_to|DBIx::Class::Relationship/belongs_to>, L<many_to_many|DBIx::Class::Relationship/many_to_many>
=item L<DBIx::Class::Relationship::Base>
L<register_relationship|DBIx::Class::Relationship::Base/register_relationship>, L<count_related|DBIx::Class::Relationship::Base/count_related>, L<create_related|DBIx::Class::Relationship::Base/create_related>, L<delete_related|DBIx::Class::Relationship::Base/delete_related>, L<find_or_create_related|DBIx::Class::Relationship::Base/find_or_create_related>, L<find_or_new_related|DBIx::Class::Relationship::Base/find_or_new_related>, L<find_related|DBIx::Class::Relationship::Base/find_related>, L<new_related|DBIx::Class::Relationship::Base/new_related>, L<related_resultset|DBIx::Class::Relationship::Base/related_resultset>, L<search_related|DBIx::Class::Relationship::Base/search_related>, L<search_related_rs|DBIx::Class::Relationship::Base/search_related_rs>, L<set_from_related|DBIx::Class::Relationship::Base/set_from_related>, L<update_from_related|DBIx::Class::Relationship::Base/update_from_related>, L<update_or_create_related|DBIx::Class::Relationship::Base/update_or_create_related>
=item L<DBIx::Class::InflateColumn>
L<get_inflated_column|DBIx::Class::InflateColumn/get_inflated_column>, L<inflate_column|DBIx::Class::InflateColumn/inflate_column>, L<set_inflated_column|DBIx::Class::InflateColumn/set_inflated_column>, L<store_inflated_column|DBIx::Class::InflateColumn/store_inflated_column>
=item L<DBIx::Class::PK>
L<ID|DBIx::Class::PK/ID>, L<id|DBIx::Class::PK/id>, L<ident_condition|DBIx::Class::PK/ident_condition>
=item L<DBIx::Class::Row>
L<delete|DBIx::Class::Row/delete>, L<update|DBIx::Class::Row/update>, L<copy|DBIx::Class::Row/copy>, L<discard_changes|DBIx::Class::Row/discard_changes>, L<get_column|DBIx::Class::Row/get_column>, L<get_columns|DBIx::Class::Row/get_columns>, L<get_dirty_columns|DBIx::Class::Row/get_dirty_columns>, L<get_from_storage|DBIx::Class::Row/get_from_storage>, L<get_inflated_columns|DBIx::Class::Row/get_inflated_columns>, L<has_column_loaded|DBIx::Class::Row/has_column_loaded>, L<in_storage|DBIx::Class::Row/in_storage>, L<inflate_result|DBIx::Class::Row/inflate_result>, L<insert|DBIx::Class::Row/insert>, L<insert_or_update|DBIx::Class::Row/insert_or_update>, L<is_changed|DBIx::Class::Row/is_changed>, L<is_column_changed|DBIx::Class::Row/is_column_changed>, L<make_column_dirty|DBIx::Class::Row/make_column_dirty>, L<new|DBIx::Class::Row/new>, L<register_column|DBIx::Class::Row/register_column>, L<result_source|DBIx::Class::Row/result_source>, L<set_column|DBIx::Class::Row/set_column>, L<set_columns|DBIx::Class::Row/set_columns>, L<set_inflated_columns|DBIx::Class::Row/set_inflated_columns>, L<store_column|DBIx::Class::Row/store_column>, L<throw_exception|DBIx::Class::Row/throw_exception>, L<update_or_insert|DBIx::Class::Row/update_or_insert>
=item L<DBIx::Class::ResultSourceProxy::Table>
L<table|DBIx::Class::ResultSourceProxy::Table/table>, L<table_class|DBIx::Class::ResultSourceProxy::Table/table_class>
=item L<DBIx::Class::ResultSource>
L<add_column|DBIx::Class::ResultSource/add_column>, L<add_columns|DBIx::Class::ResultSource/add_columns>, L<add_relationship|DBIx::Class::ResultSource/add_relationship>, L<add_unique_constraint|DBIx::Class::ResultSource/add_unique_constraint>, L<add_unique_constraints|DBIx::Class::ResultSource/add_unique_constraints>, L<column_info|DBIx::Class::ResultSource/column_info>, L<column_info_from_storage|DBIx::Class::ResultSource/column_info_from_storage>, L<columns|DBIx::Class::ResultSource/columns>, L<columns_info|DBIx::Class::ResultSource/columns_info>, L<has_column|DBIx::Class::ResultSource/has_column>, L<has_relationship|DBIx::Class::ResultSource/has_relationship>, L<primary_columns|DBIx::Class::ResultSource/primary_columns>, L<relationship_info|DBIx::Class::ResultSource/relationship_info>, L<relationships|DBIx::Class::ResultSource/relationships>, L<remove_column|DBIx::Class::ResultSource/remove_column>, L<remove_columns|DBIx::Class::ResultSource/remove_columns>, L<result_class|DBIx::Class::ResultSource/result_class>, L<resultset_attributes|DBIx::Class::ResultSource/resultset_attributes>, L<resultset_class|DBIx::Class::ResultSource/resultset_class>, L<sequence|DBIx::Class::ResultSource/sequence>, L<set_primary_key|DBIx::Class::ResultSource/set_primary_key>, L<source_info|DBIx::Class::ResultSource/source_info>, L<source_name|DBIx::Class::ResultSource/source_name>, L<unique_constraint_columns|DBIx::Class::ResultSource/unique_constraint_columns>, L<unique_constraint_names|DBIx::Class::ResultSource/unique_constraint_names>, L<unique_constraints|DBIx::Class::ResultSource/unique_constraints>
=back
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.

View File

@@ -0,0 +1,169 @@
=head1 NAME
DBIx::Class::Manual::Troubleshooting - Got a problem? Shoot it.
=head2 "Can't locate storage blabla"
You're trying to make a query on a non-connected schema. Make sure you got
the current resultset from $schema->resultset('Artist') on a schema object
you got back from connect().
=head2 Tracing SQL
The C<DBIC_TRACE> environment variable controls
SQL tracing, so to see what is happening try
export DBIC_TRACE=1
Alternatively use the C<< storage->debug >> class method:-
$schema->storage->debug(1);
To send the output somewhere else set debugfh:-
$schema->storage->debugfh(IO::File->new('/tmp/trace.out', 'w'));
Alternatively you can do this with the environment variable, too:-
export DBIC_TRACE="1=/tmp/trace.out"
=head2 Can't locate method result_source_instance
For some reason the table class in question didn't load fully, so the
ResultSource object for it hasn't been created. Debug this class in
isolation, then try loading the full schema again.
=head2 Can't get last insert ID under Postgres with serial primary keys
Older L<DBI> and L<DBD::Pg> versions do not handle C<last_insert_id>
correctly, causing code that uses auto-incrementing primary key
columns to fail with a message such as:
Can't get last insert id at /.../DBIx/Class/Row.pm line 95
In particular the RHEL 4 and FC3 Linux distributions both ship with
combinations of L<DBI> and L<DBD::Pg> modules that do not work
correctly.
L<DBI> version 1.50 and L<DBD::Pg> 1.43 are known to work.
=head2 Can't locate object method "source_name" via package
There's likely a syntax error in the table class referred to elsewhere
in this error message. In particular make sure that the package
declaration is correct. For example, for a schema C< MySchema >
you need to specify a fully qualified namespace: C< package MySchema::MyTable; >.
=head2 syntax error at or near "<something>" ...
This can happen if you have a relation whose name is a word reserved by your
database, e.g. "user":
package My::Schema::User;
...
__PACKAGE__->table('users');
__PACKAGE__->add_columns(qw/ id name /);
__PACKAGE__->set_primary_key('id');
...
1;
package My::Schema::ACL;
...
__PACKAGE__->table('acl');
__PACKAGE__->add_columns(qw/ user_id /);
__PACKAGE__->belongs_to( 'user' => 'My::Schema::User', 'user_id' );
...
1;
$schema->resultset('ACL')->search(
{},
{
join => [qw/ user /],
'+select' => [ 'user.name' ]
}
);
The SQL generated would resemble something like:
SELECT me.user_id, user.name FROM acl me
JOIN users user ON me.user_id = user.id
If, as is likely, your database treats "user" as a reserved word, you'd end
up with the following errors:
1) syntax error at or near "." - due to "user.name" in the SELECT clause
2) syntax error at or near "user" - due to "user" in the JOIN clause
The solution is to enable quoting - see
L<DBIx::Class::Manual::Cookbook/Setting quoting for the generated SQL> for
details.
=head2 column "foo DESC" does not exist ...
This can happen if you are still using the obsolete order hack, and also
happen to turn on SQL-quoting.
$rs->search( {}, { order_by => [ 'name DESC' ] } );
The above should be written as:
$rs->search( {}, { order_by => { -desc => 'name' } } );
For more ways to express order clauses refer to
L<SQL::Abstract::Classic/ORDER BY CLAUSES>
=head2 Perl Performance Issues on Red Hat Systems
There is a problem with slow performance of certain DBIx::Class
operations using the system perl on some Fedora and Red Hat Enterprise
Linux system (as well as their derivative distributions such as Centos,
White Box and Scientific Linux).
Distributions affected include Fedora 5 through to Fedora 8 and RHEL5
up to and including RHEL5 Update 2. Fedora 9 (which uses perl 5.10) has
never been affected - this is purely a perl 5.8.8 issue.
As of September 2008 the following packages are known to be fixed and so
free of this performance issue (this means all Fedora and RHEL5 systems
with full current updates will not be subject to this problem):-
Fedora 8 - perl-5.8.8-41.fc8
RHEL5 - perl-5.8.8-15.el5_2.1
This issue is due to perl doing an exhaustive search of blessed objects
under certain circumstances. The problem shows up as performance
degradation exponential to the number of L<DBIx::Class> result objects in
memory, so can be unnoticeable with certain data sets, but with huge
performance impacts on other datasets.
A pair of tests for susceptibility to the issue and performance effects
of the bless/overload problem can be found in the L<DBIx::Class> test
suite, in the C<t/99rh_perl_perf_bug.t> file.
Further information on this issue can be found in
L<https://bugzilla.redhat.com/show_bug.cgi?id=379791>,
L<https://bugzilla.redhat.com/show_bug.cgi?id=460308> and
L<http://rhn.redhat.com/errata/RHBA-2008-0876.html>
=head2 Excessive Memory Allocation with TEXT/BLOB/etc. Columns and Large LongReadLen
It has been observed, using L<DBD::ODBC>, that creating a L<DBIx::Class::Row>
object which includes a column of data type TEXT/BLOB/etc. will allocate
LongReadLen bytes. This allocation does not leak, but if LongReadLen
is large in size, and many such result objects are created, e.g. as the
output of a ResultSet query, the memory footprint of the Perl interpreter
can grow very large.
The solution is to use the smallest practical value for LongReadLen.
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
=head1 COPYRIGHT AND LICENSE
This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
redistribute it and/or modify it under the same terms as the
L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.