The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Catalyst::Model::Jifty::DBI - Jifty::DBI Model Class with some magic on top

SYNOPSIS

In your model class:

  package MyApp::Model:
  use strict;
  use base qw( Catalyst::Model::Jifty::DBI );
  __PACKAGE__->config({
      schema_base  => 'MyApp::Schema',
      connect_info => {
          driver   => 'SQLite',
          database => 'myapp.db',
      },
  });
  1;

Or you may want to have multiple databases (for partitioning):

  package MyApp::Model:
  use strict;
  use base qw( Catalyst::Model::Jifty::DBI );
  __PACKAGE__->config({
      schema_base => 'MyApp::Schema',
      databases   => [
          {
              name => 'database1',
              connect_info => {
                  driver   => 'SQLite',
                  database => 'myapp1.db',
              },
          },
          {
              name => 'database2',
              connect_info => {
                  driver   => 'SQLite',
                  database => 'myapp2.db',
              },
          },
      ],
  });
  1;

Then in a controller:

  my $record = $c->model('JDBI::Book');
     $record->load_by_cols( name => 'foo' );

  my $collection = $c->model('JDBI::BookCollection');
     $collection->limit( column => 'name', value => 'bar',
                         operator => 'MATCHES' );

Or, you may want to do more explicitly

  my $record = $c->model('JDBI')->record('Book');
     $record->load_by_cols( name => 'foo' );

  my $collection = $c->model('JDBI')->collection('BookCollection');
     $collection->limit( column => 'name', value => 'bar',
                         operator => 'MATCHES' );

If you want some partitioning:

  my $record_1 = $c->model('JDBI')
                   ->record('Book', from => 'database1');
  my $record_2 = $c->model('JDBI')
                   ->record('Book', from => 'database2');

  my $collection_1 = $c->model('JDBI')
                       ->collection('BookCollection',
                                    from => 'database1');
  my $collection_2 = $c->model('JDBI')
                       ->collection('BookCollection',
                                    from => 'database2');

You can also setup a database:

  my $database = $c->model('JDBI')->database;
  if ( $database && -f $database ) {
    $c->model('JDBI')->disconnect;
    unlink $database;
  }
  $c->model('JDBI')->setup_database;

You want more? or you don't want any more magic?

  my $handle = $c->model('JDBI')->handle;
  my $sth = $handle->simple_query( $sql_statement, @binds );

  # Also you can write like this if you use a default handle:
  my $sth = $c->model('JDBI')
              ->simple_query( $sql_statement, @binds );

When you want to debug (against the default handle):

  $c->model('JDBI')->trace(1);  # start logging
  $c->model('JDBI')->trace(0);  # stop logging

BACKWARD INCOMPATIBILITY

Current version of Catalyst::Model::Jifty::DBI was once called Catalyst::Model::JDBI::Schemas, which then replaced the original version written by Marcus Ramberg, by the request of Matt S. Trout (Catalyst Core team) to avoid future confusion. I wonder if anyone used the previous one, but note that APIs have been revamped and backward incompatible since 0.03.

DESCRIPTION

This is a Catalyst model for Jifty::DBI-based schemas, which may or may not be placed under your model class (if you don't want to place them under the model class, pass "schema_base" option to the model). The model class automatically detect/load your schemas, like Catalyst::Model::DBIC::Schema does.

This model also provides several features for laziness. You don't have to create simple Collection classes (they'll be created on the fly a la Jifty). No more writing schema in other language just to set up databases; C::M::Jifty::DBI takes care of it, on the fly if you want (of course from the perl schemas you prepared; converting raw SQLs to a database to perl schemas is not our way). You may want to use multiple databases of the same schema, or, you may prefer bloody raw SQL statements to complicated object chains. Here you are. Have fun!

CONFIG

schema_base

The namespace to look for schema definitions in. All the schemas just below this namespace would be counted.

connect_info

A hash reference, which would be converted to a hash, then be passed to Jifty::DBI::Handle->new. See Jifty::DBI::Handle for details.

databases

You may want to use multiple databases (for log rotation, load balancing etc). In this case you can provide multiple "connect_info" hash references under here, as shown in the SYNOPSIS. Actually, above "connect_info" hash reference would be moved in this "databases" array reference internally, with a default name "_" (underscore).

METHODS

new

creates a model. Database connection may or may not be prepared, according to the number of connect_info. See above for the configuration.

record

creates and returns a corresponding (new) Jifty::DBI::Record object. Note that this is just a Record, not a Collection or a RecordSet of DBIC. That means, this object holds one and only single record, and usually you shouldn't reuse this object to let it hold another record. See examples:

  # this works.
  my $record = $c->model('JDBI')->record('Book');
     $record->load_by_cols( id => 1 );
     $record->set_name( 'new name' );  # now inserted/updated

  # this may or may not work as you wish,
  # depending on what you really want to do.
  $c->model('JDBI')->record('Book')->load_by_cols( id => 1 );
  $c->model('JDBI')->record('Book')->set_name( 'new name' );

You can pass an optional hash, as shown in the SYNOPSIS.

  # this tries to fetch a record from a table named 'books'
  # in a database named 'database'.
  my $record = $c->model('JDBI')->record('Book', from => 'database');

You can omit "->record" when you fetch from a default database.

  # both do the same thing
  my $record = $c->model('JDBI')->record('Book');
  my $record = $c->model('JDBI::Book');

collection

creates and returns a corresponding (new) Jifty::DBI::Collection object. If you haven't created a Collection class but only a Schema/Record class, this model creates a plain Collection class on the fly. I recommend not to omit the obvious 'Collection' part of the class name, but if you prefer, you can spare that when you explicitly call model("Model")->collection("Schema") (you can't omit if you follow the model("Model::Schema") convention). Other general usage and caveats are the same as ->record.

  # this works.
  my $collection = $c->model('JDBI')->collection('BookCollection');
     $collection->unlimit;
     $collection->limit( column => 'name', value => 'bar',
                         operator => 'MATCHES' );

  # this may or may not work as you wish,
  # depending on what you really want to do.
  $c->model('JDBI')->collection('BookCollection')->limit;
  $c->model('JDBI')->collection('BookCollection')->first;

You can pass an optional hash, as shown in the SYNOPSIS.

  # this tries to fetch a collection from a table named 'books'
  # in a database named 'database'.
  my $collection = $c->model('JDBI')
                     ->collection('BookCollection',
                                  from => 'database');

You can omit "->collection" when you fetch from a default database.

  # both do the same thing
  my $collection = $c->model('JDBI')->collection('BookCollection');
  my $collection = $c->model('JDBI::BookCollection');

simple_query

When you want to do something irrelevant to a specific table, or something too complicated for Jifty::DBI, you can execute arbitrary statements with "simple_query", which is almost equivalent to DBI's $dbh->do or ->prepare. Note that this is supposed to use a default handle. If you want to use other handles, get the handle first with ->handle described below.

  # fetch something from "tables" table,
  # described in "(Your::Schema::)Table" schema/record class.
  my $statement = 'select * from tables where id = ?';
  my $sth = $c->model('JDBI')->simple_query( $statement, 1 );
  return $sth ? $sth->fetchrow : undef;

  # Above is equivalent to:
  my $handle = $c->model('JDBI')->handle;
  my $sth = $handle->simple_query( $statement, 1 );
  return $sth ? $sth->fetchrow : undef;

fetch_result

This is a lazier shortcut to realize the example just shown above.

  my $statement = 'select * from tables where id = ?';
  my $row = $c->model('JDBI')->fetch_result( $statement, 1 );

handle

C::M::Jifty::DBI may have multiple JDBI handles. You can choose one you want to use like this:

  my $handle = $c->model('JDBI')->handle( name => 'sample.db' );

You can use "from" instead of "name". Also, you can use an alias to the real database name (connect_info->{database}) if you set "name" option in the config.

  my $handle = $c->model('JDBI')->handle( from => 'alias' );

By default, this returns a default handle.

default_handle_name

returns (or sets) a default handle/database name.

databases

returns all the database names/aliases registered in the config.

  # See if all the registered SQLite databases have been set up.
  foreach my $name ( $c->model('JDBI')->databases ) {
    my $dbfile = $c->model('JDBI')->database( name => $name );
    warn "database $db does not exist" unless -f $dbfile;
    warn "database $db is blank" unless -s $dbfile;
  }

database

returns a database name (or an actual path to the database for SQLite). See above for an example. You can pass an optional hash to specify database alias explicitly.

  $c->model('JDBI')->database( name => 'alias' );

As of 0.06, this returns a blank string if the driver is SQLite and the atabase is ":memory:", which means the whole database is on the memory, and there's no real file to operate.

setup_database

You can set up database on the fly with your perl schema. You can pass an optional hash to specify target database.

  $c->model('JDBI')->setup_database( name => 'database' );

begin_transaction

commit

rollback

These three are shortcuts to ->handle->(method_name). You can pass an optional hash to specify target database.

disconnect

This also is a shortcut to ->handle->disconnect. You can pass an optional hash to specify target database.

trace

turns on and off the logging of sql statements. If this is set to true, C::M::Jifty::DBI spits the info to STDERR. If you want finer control, give it a code reference.

  $c->model('JDBI')->trace(sub {
    my ($time, $statement, $binding, $duration, $result) = @_;
    warn $statement, "\n", @$binding;
  });

See Jifty::DBI::Handle for details (log_sql_hook / sql_statement_log).

SEE ALSO

Jifty::DBI

AUTHOR

Kenichi Ishigaki, <ishigaki@cpan.org>

original version is written by Marcus Ramberg, <mramberg@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2007 by Kenichi Ishigaki.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.