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

NAME

DBIx::Class::Schema - composable schemas

SYNOPSIS

  package Library::Schema;
  use base qw/DBIx::Class::Schema/;
  
  # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
  __PACKAGE__->load_classes(qw/CD Book DVD/);

  package Library::Schema::CD;
  use base qw/DBIx::Class/;
  __PACKAGE__->load_components(qw/PK::Auto Core/); # for example
  __PACKAGE__->table('cd');

  # Elsewhere in your code:
  my $schema1 = Library::Schema->connect(
    $dsn,
    $user,
    $password,
    { AutoCommit => 0 },
  );
  
  my $schema2 = Library::Schema->connect($coderef_returning_dbh);

  # fetch objects using Library::Schema::DVD
  my $resultset = $schema1->resultset('DVD')->search( ... );
  my @dvd_objects = $schema2->resultset('DVD')->search( ... );

DESCRIPTION

Creates database classes based on a schema. This is the recommended way to use DBIx::Class and allows you to use more than one concurrent connection with your classes.

NB: If you're used to Class::DBI it's worth reading the "SYNOPSIS" carefully, as DBIx::Class does things a little differently. Note in particular which module inherits off which.

METHODS

register_class

Arguments: $moniker, $component_class

Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to calling:

  $schema->register_source($moniker, $component_class->result_source_instance);

register_source

Arguments: $moniker, $result_source

Registers the DBIx::Class::ResultSource in the schema with the given moniker.

class

Arguments: $moniker
Return Value: $classname

Retrieves the result class name for the given moniker. For example:

  my $class = $schema->class('CD');

source

Arguments: $moniker
Return Value: $result_source
  my $source = $schema->source('Book');

Returns the DBIx::Class::ResultSource object for the registered moniker.

sources

Return Value: @source_monikers

Returns the source monikers of all source registrations on this schema. For example:

  my @source_monikers = $schema->sources;

resultset

Arguments: $moniker
Return Value: $result_set
  my $rs = $schema->resultset('DVD');

Returns the DBIx::Class::ResultSet object for the registered moniker.

load_classes

Arguments: @classes?, { $namespace => [ @classes ] }+

With no arguments, this method uses Module::Find to find all classes under the schema's namespace. Otherwise, this method loads the classes you specify (using use), and registers them (using "register_class").

It is possible to comment out classes with a leading #, but note that perl will think it's a mistake (trying to use a comment in a qw list), so you'll need to add no warnings 'qw'; before your load_classes call.

Example:

  My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
                              # etc. (anything under the My::Schema namespace)

  # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
  # not Other::Namespace::LinerNotes nor My::Schema::Track
  My::Schema->load_classes(qw/ CD Artist #Track /, {
    Other::Namespace => [qw/ Producer #LinerNotes /],
  });

compose_connection

Arguments: $target_namespace, @db_info
Return Value: $new_schema

Calls "compose_namespace" in DBIx::Class::Schema to the target namespace, calls "connection" in DBIx::Class::Schema with @db_info on the new schema, then injects the DBix::Class::ResultSetProxy component and a resultset_instance classdata entry on all the new classes, in order to support $target_namespaces::$class->search(...) method calls.

This is primarily useful when you have a specific need for class method access to a connection. In normal usage it is preferred to call "connect" in DBIx::Class::Schema and use the resulting schema object to operate on DBIx::Class::ResultSet objects with "resultset" in DBIx::Class::Schema for more information.

compose_namespace

Arguments: $target_namespace, $additional_base_class?
Return Value: $new_schema

For each DBIx::Class::ResultSource in the schema, this method creates a class in the target namespace (e.g. $target_namespace::CD, $target_namespace::Artist) that inherits from the corresponding classes attached to the current schema.

It also attaches a corresponding DBIx::Class::ResultSource object to the new $schema object. If $additional_base_class is given, the new composed classes will inherit from first the corresponding classe from the current schema then the base class.

For example, for a schema with My::Schema::CD and My::Schema::Artist classes,

  $schema->compose_namespace('My::DB', 'Base::Class');
  print join (', ', @My::DB::CD::ISA) . "\n";
  print join (', ', @My::DB::Artist::ISA) ."\n";

will produce the output

  My::Schema::CD, Base::Class
  My::Schema::Artist, Base::Class

setup_connection_class

Arguments: $target, @info

Sets up a database connection class to inject between the schema and the subclasses that the schema creates.

connection

Arguments: @args
Return Value: $new_schema

Instantiates a new Storage object of type "storage_type" in DBIx::Class::Schema and passes the arguments to $storage->connect_info. Sets the connection in-place on the schema. See "connect_info" in DBIx::Class::Storage::DBI for more information.

connect

Arguments: @info
Return Value: $new_schema

This is a convenience method. It is equivalent to calling $schema->clone->connection(@info). See "connection" and "clone" for more information.

txn_begin

Begins a transaction (does nothing if AutoCommit is off). Equivalent to calling $schema->storage->txn_begin. See "txn_begin" in DBIx::Class::Storage::DBI for more information.

txn_commit

Commits the current transaction. Equivalent to calling $schema->storage->txn_commit. See "txn_commit" in DBIx::Class::Storage::DBI for more information.

txn_rollback

Rolls back the current transaction. Equivalent to calling $schema->storage->txn_rollback. See "txn_rollback" in DBIx::Class::Storage::DBI for more information.

txn_do

Arguments: $coderef, @coderef_args?
Return Value: The return value of $coderef

Executes $coderef with (optional) arguments @coderef_args atomically, returning its result (if any). If an exception is caught, a rollback is issued and the exception is rethrown. If the rollback fails, (i.e. throws an exception) an exception is thrown that includes a "Rollback failed" message.

For example,

  my $author_rs = $schema->resultset('Author')->find(1);

  my $coderef = sub {
    my ($author, @titles) = @_;

    # If any one of these fails, the entire transaction fails
    $author->create_related('books', {
      title => $_
    }) foreach (@titles);

    return $author->books;
  };

  my $rs;
  eval {
    $rs = $schema->txn_do($coderef, $author_rs, qw/Night Day It/);
  };

  if ($@) {
    my $error = $@;
    if ($error =~ /Rollback failed/) {
      die "something terrible has happened!";
    } else {
      deal_with_failed_transaction();
    }
  }

In a nested transaction (calling txn_do() from within a txn_do() coderef) only the outermost transaction will issue a "txn_commit" in DBIx::Class::Schema on the Schema's storage, and txn_do() can be called in void, scalar and list context and it will behave as expected.

clone

Return Value: $new_schema

Clones the schema and its associated result_source objects and returns the copy.

populate

Arguments: $moniker, \@data;

Populates the source registered with the given moniker with the supplied data. @data should be a list of listrefs -- the first containing column names, the second matching values.

i.e.,

  $schema->populate('Artist', [
    [ qw/artistid name/ ],
    [ 1, 'Popular Band' ],
    [ 2, 'Indie Band' ],
    ...
  ]);

throw_exception

Arguments: $message

Throws an exception. Defaults to using Carp::Clan to report errors from user's perspective.

deploy (EXPERIMENTAL)

Arguments: $sqlt_args

Attempts to deploy the schema to the current storage using SQL::Translator.

Note that this feature is currently EXPERIMENTAL and may not work correctly across all databases, or fully handle complex relationships.

AUTHORS

Matt S. Trout <mst@shadowcatsystems.co.uk>

LICENSE

You may distribute this code under the same terms as Perl itself.