Initial Commit
This commit is contained in:
144
database/perl/vendor/lib/DBIx/Class/Manual/Component.pod
vendored
Normal file
144
database/perl/vendor/lib/DBIx/Class/Manual/Component.pod
vendored
Normal 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>.
|
||||
2285
database/perl/vendor/lib/DBIx/Class/Manual/Cookbook.pod
vendored
Normal file
2285
database/perl/vendor/lib/DBIx/Class/Manual/Cookbook.pod
vendored
Normal file
File diff suppressed because it is too large
Load Diff
74
database/perl/vendor/lib/DBIx/Class/Manual/DocMap.pod
vendored
Normal file
74
database/perl/vendor/lib/DBIx/Class/Manual/DocMap.pod
vendored
Normal 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>.
|
||||
|
||||
115
database/perl/vendor/lib/DBIx/Class/Manual/Example.pod
vendored
Normal file
115
database/perl/vendor/lib/DBIx/Class/Manual/Example.pod
vendored
Normal 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
|
||||
706
database/perl/vendor/lib/DBIx/Class/Manual/FAQ.pod
vendored
Normal file
706
database/perl/vendor/lib/DBIx/Class/Manual/FAQ.pod
vendored
Normal 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>.
|
||||
677
database/perl/vendor/lib/DBIx/Class/Manual/Features.pod
vendored
Normal file
677
database/perl/vendor/lib/DBIx/Class/Manual/Features.pod
vendored
Normal 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>.
|
||||
167
database/perl/vendor/lib/DBIx/Class/Manual/Glossary.pod
vendored
Normal file
167
database/perl/vendor/lib/DBIx/Class/Manual/Glossary.pod
vendored
Normal 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>.
|
||||
483
database/perl/vendor/lib/DBIx/Class/Manual/Intro.pod
vendored
Normal file
483
database/perl/vendor/lib/DBIx/Class/Manual/Intro.pod
vendored
Normal 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>.
|
||||
286
database/perl/vendor/lib/DBIx/Class/Manual/Joining.pod
vendored
Normal file
286
database/perl/vendor/lib/DBIx/Class/Manual/Joining.pod
vendored
Normal 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>.
|
||||
205
database/perl/vendor/lib/DBIx/Class/Manual/QuickStart.pod
vendored
Normal file
205
database/perl/vendor/lib/DBIx/Class/Manual/QuickStart.pod
vendored
Normal 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>.
|
||||
191
database/perl/vendor/lib/DBIx/Class/Manual/Reading.pod
vendored
Normal file
191
database/perl/vendor/lib/DBIx/Class/Manual/Reading.pod
vendored
Normal 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>.
|
||||
103
database/perl/vendor/lib/DBIx/Class/Manual/ResultClass.pod
vendored
Normal file
103
database/perl/vendor/lib/DBIx/Class/Manual/ResultClass.pod
vendored
Normal 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>.
|
||||
|
||||
169
database/perl/vendor/lib/DBIx/Class/Manual/Troubleshooting.pod
vendored
Normal file
169
database/perl/vendor/lib/DBIx/Class/Manual/Troubleshooting.pod
vendored
Normal 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>.
|
||||
Reference in New Issue
Block a user