be alarmed if the error from incorrect connection details happens a
lot later.
+=item .. use DBIx::Class across multiple databases?
-=back
+If your database server allows you to run querys 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<DBIx::Class::ResultSource/table> call. Eg:
+
+ __PACKAGE__->table('mydb.mytablename');
+
+And load all the Result classes for both / all databases using one
+L<DBIx::Class::Schema/load_namespaces> call.
+
+=item .. use DBIx::Class across PostgreSQL/DB2/Oracle schemas?
+
+Add the name of the schema to the L<DBIx::Class::ResultSource/table>
+as part of the name, and make sure you give the one user you are going
+to connect with rights to read/write all the schemas/tables as
+necessary.
+
+=back
=head2 Relationships
=item .. tell DBIx::Class about relationships between my tables?
-There are a vareity of relationship types that come pre-defined for
+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>.
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?
+=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
Read the documentation on L<DBIx::Class::Relationship/many_to_many>.
-=item .. stop DBIx::Class from attempting to cascade deletes on my has_many relationships?
+=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> relationships. If your database already does this (and
-that is probably better), turn it off by supplying C<< cascade_delete => 0 >>
-in the relationship attributes. See L<DBIx::Class::Relationship::Base>.
+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?
Or, if you have quoting off:
- ->search({ 'YEAR(date_of_birth' => 1979 });
+ ->search({ 'YEAR(date_of_birth)' => 1979 });
=item .. find more help on constructing searches?
L<DBIx::Class::Manual::Cookbook>, try looking in the SQL::Abstract
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'");
+
+
=back
=head2 Fetching data
=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 it's documentation and the
+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?
=item .. fetch a single (or topmost) row?
-Sometimes you many only want a single record back from a search. A quick
-way to get that single row is to first run your search as usual:
+See L<DBIx::Class::Manual::Cookbook/Retrieve_one_and_only_one_row_from_a_resultset>.
- ->search->(undef, { order_by => "id DESC" })
+A less readable way is to ask a regular search to return 1 row, using
+L<DBIx::Class::ResultSet/slice>:
-Then call L<DBIx::Class::ResultSet/slice> and ask it only to return 1 row:
+ ->search->(undef, { order_by => "id DESC" })->slice(0)
- ->slice(0,1)
-
-These two calls can be combined into a single statement:
-
- ->search->(undef, { order_by => "id DESC" })->slice(0,1)
-
-Why slice instead of L<DBIx::Class::ResultSet/first> or L<DBIx::Class::ResultSet/single>?
-If supported by the database, slice will use LIMIT/OFFSET to hint to the database that we
-really only need one row. This can result in a significant speed improvement.
+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?
L<DBIx::Class::PK/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<Data::Page>
+object. 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
But note that when using a scalar reference the column in the database
will be updated but when you read the value from the object with e.g.
-
+
->somecolumn()
-
+
you still get back the scalar reference to the string, B<not> the new
value in the database. To get that you must refresh the row from storage
using C<discard_changes()>. Or chain your function calls like this:
->update->discard_changes
-
- to update the database and refresh the object in one step.
-
+
+to update the database and refresh the object in one step.
+
=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.
You can add your own data accessors to your classes.
+One method is to use the built in mk_group_accessors (via L<Class::Accessor::Grouped>)
+
+ package MyTable;
+
+ use parent 'DBIx::Class';
+
+ __PACKAGE__->table('foo'); #etc
+ __PACKAGE__->mk_group_accessors('simple' => qw/non_column_data/); # must use simple group
+
+An another method is to use L<Moose> with your L<DBIx::Class> package.
+
+ package MyTable;
+
+ use Moose; # import Moose
+ use Moose::Util::TypeConstraint; # import Moose accessor type constraints
+
+ extends 'DBIx::Class'; # 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 accesssor would be
+
+ my $row;
+
+ # assume that somewhere in here $row will get assigned to a MyTable row
+
+ $row->non_column_data('some string'); # would set the non_column_data accessor
+
+ # some other stuff happens here
+
+ $row->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
$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 row object creation for faster results">
+and L<DBIx::Class::Manual::Cookbook/"Get raw data for blindingly fast results">
+
=back
=head2 Notes for CDBI users
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 chance 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