NAME

DBIO::Schema - Schema class and connection container for DBIO applications

VERSION

version 0.900004

SYNOPSIS

package Library::Schema;
use DBIO 'Schema', -pg;

# load all Result classes in Library/Schema/Result/
__PACKAGE__->load_namespaces();

package Library::Schema::Result::CD;
use base qw/DBIO::Core/;

__PACKAGE__->load_components(qw/InflateColumn::DateTime/); # for example
__PACKAGE__->table('cd');

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

my $schema2 = Library::Schema->connect($coderef_returning_dbh);

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

See t/39load_namespaces_1.t for a runnable example.

DESCRIPTION

DBIO::Schema is the central class for a DBIO application. It owns the registered result sources, mediates access to storage, and provides the usual entry points such as connect, resultset, and source.

Using a dedicated schema class is the normal way to structure a DBIO application, and it allows the same result classes to be used with more than one concurrent connection when needed.

METHODS

connect

Arguments: @connectinfo
Return Value: $new_schema

Creates and returns a new Schema object. The connection info set on it is used to create a new instance of the storage backend and set it on the Schema object.

See "connect_info" in DBIO::Storage::DBI for DBI-specific syntax on the @connectinfo argument, or DBIO::Storage in general.

Note that connect_info expects an arrayref of arguments, but connect does not. connect wraps its arguments in an arrayref before passing them to connect_info.

Overloading

connect is a convenience method. It is equivalent to calling $schema->clone->connection(@connectinfo). To write your own overloaded version, overload "connection" instead.

resultset

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

Returns the DBIO::ResultSet object for the registered source name.

sources

Return Value: @source_names
my @source_names = $schema->sources;

Lists names of all the sources registered on this Schema object, sorted by name. The order is the same in every process, so text written by walking the list (one statement per table, say) does not change from one run to the next. In scalar context, returns the number of sources.

source

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

Returns the DBIO::ResultSource object for the registered source name.

datetime_parser

my $parser = $schema->datetime_parser;

Returns the datetime parser of the schema's storage. Equivalent to calling $schema->storage->datetime_parser; see "datetime_parser" in DBIO::Storage::DBI.

parse_datetime

my $dt = $schema->parse_datetime($string);

Shortcut for $schema->datetime_parser->parse_datetime(@args).

format_datetime

my $string = $schema->format_datetime($dt);

Shortcut for $schema->datetime_parser->format_datetime(@args).

skills

MyApp::Schema->skills({ 'mysql-database' => $markdown });
my $overrides = $schema->skills;

Class data holding this schema's skill overrides: a hashref mapping skill names (the leading dbio- is optional) to markdown text, or undef when none are set. "skill" consults it before the bundled skills. A class written with use DBIO 'Schema' can declare the map with the skills / skill keywords (see "USE-AS-PRAGMA" in DBIO).

A skills key in a hashref passed to "connect" sets the overrides for that schema object only. It replaces the class-level map there rather than being merged into it, and is removed from the hashref before the connect info reaches the storage:

my $schema = MyApp::Schema->connect($dsn, $user, $pass, {
  skills => { core => $markdown },
});

skill

my $markdown = $schema->skill('mysql-database');

Return the markdown text of the named agent skill (see DBIO::Skills). The leading dbio- is optional. A per-schema override set via the skills class data (or the skills connect option) wins; otherwise the skill is resolved from the bundled sharedirs of the loaded DBIO distributions, including this schema's own driver.

SETUP METHODS

load_namespaces

Arguments: %options?
package MyApp::Schema;
__PACKAGE__->load_namespaces();

__PACKAGE__->load_namespaces(
   result_namespace => 'Res',
   resultset_namespace => 'RSet',
   default_resultset_class => '+MyApp::Othernamespace::RSet',
);

With no arguments, this method uses Module::Find to load all of the Result and ResultSet classes under the namespace of the schema from which it is called. For example, My::Schema will by default find and load Result classes named My::Schema::Result::* and ResultSet classes named My::Schema::ResultSet::*.

ResultSet classes are associated with Result class of the same name. For example, My::Schema::Result::CD will get the ResultSet class My::Schema::ResultSet::CD if it is present.

Both Result and ResultSet namespaces are configurable via the result_namespace and resultset_namespace options.

Another option, default_resultset_class specifies a custom default ResultSet class for Result classes with no corresponding ResultSet.

All of the namespace and classname options are by default relative to the schema classname. To specify a fully-qualified name, prefix it with a literal +. For example, +Other::NameSpace::Result.

Warnings

You will be warned if ResultSet classes are discovered for which there are no matching Result classes like this:

load_namespaces found ResultSet class '$classname' with no corresponding Result class

If a ResultSource instance is found to already have a ResultSet class set using resultset_class to some other class, you will be warned like this:

We found ResultSet class '$rs_class' matching '$result_class', but it seems
that you had already set the '$result_class' resultet to '$rs_set' instead

Examples

# load My::Schema::Result::CD, My::Schema::Result::Artist,
#    My::Schema::ResultSet::CD, etc...
My::Schema->load_namespaces;

# Override everything to use ugly names.
# In this example, if there is a My::Schema::Res::Foo, but no matching
#   My::Schema::RSets::Foo, then Foo will have its
#   resultset_class set to My::Schema::RSetBase
My::Schema->load_namespaces(
  result_namespace => 'Res',
  resultset_namespace => 'RSets',
  default_resultset_class => 'RSetBase',
);

# Put things in other namespaces
My::Schema->load_namespaces(
  result_namespace => '+Some::Place::Results',
  resultset_namespace => '+Another::Place::RSets',
);

To search multiple namespaces for either Result or ResultSet classes, use an arrayref of namespaces for that option. In the case that the same result (or resultset) class exists in multiple namespaces, later entries in the list of namespaces will override earlier ones.

My::Schema->load_namespaces(
  # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
  result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
  resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
);

load_classes

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

"load_classes" is an alternative method to "load_namespaces", both of which serve similar purposes, each with different advantages and disadvantages. In the general case you should use "load_namespaces", unless you need to be able to specify that only specific classes are loaded at runtime.

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.

If any classes found do not appear to be Result class files, you will get the following warning:

Failed to load $comp_class. Can't find source_name method. Is
$comp_class really a full DBIO result class? Fix it, move it elsewhere,
or make your load_classes call more specific.

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 /],
});

storage_type

Arguments: $storage_type|{$storage_type, \%args}
Return Value: $storage_type|{$storage_type, \%args}
Default value: DBIO::Storage::DBI

Set the storage class that will be instantiated when "connect" is called. If the classname starts with ::, the prefix DBIO::Storage is assumed by "connect".

This is where a schema declares its driver, and a schema always does. It is seldom set by hand: loading a driver's component (__PACKAGE__->load_components('PostgreSQL')) or using its shortcut (use DBIO 'Schema', -pg, "apply_driver" in DBIO) pins the driver's base storage class here -- DBIO::PostgreSQL::Storage, DBIO::MySQL::Storage, DBIO::SQLite::Storage, each shipped by its own driver distribution.

A declared storage class stands, whatever DSN the schema is connected with. The driver adapts itself to the access path of the connection within its own classes ("_adapt_to_access_path" in DBIO::Storage::DBI, ADR 0059); the storage never becomes the class of another driver. What does not fit -- a DSN through the DBD of another driver, a server the driver notices is not its engine -- is reported as "driver_strict" and "driver_warnings" say.

Left at the default, the generic DBIO::Storage::DBI, the schema declares no driver, and "connection" refuses it before building a storage (ADR 0067). A storage class set here before connecting -- on the class or on a clone -- is a declaration: that is how a schema shared by several drivers, such as a test schema, gets its driver per use. Which driver a DSN leads to is answered by "driver_for" in DBIO, and "schema_for" in DBIO builds a connected schema with that driver.

If your storage type requires instantiation arguments, those are defined as a second argument in the form of a hashref and the entire value needs to be wrapped into an arrayref or a hashref. We support both types of refs here in order to play nice with your Config::[class] or your choice. See DBIO::Replicated::Storage for an example of this.

driver_strict

Arguments: boolean
Default value: false

Makes a declared driver that does not fit what it meets an error: with it set, what "driver_warnings" would warn about throws, at the first use of the storage that needs the driver. It wins over driver_warnings(0).

Two things are reported, and neither costs a question to the server: the DSN leads through a DBD that belongs to another driver (a schema declaring DBIO::PostgreSQL connected with dbi:mysql:), or the driver notices, from what it knows anyway, that the server is not its engine. Only registered driver classes are checked against the DBD: a DBD no driver is registered for is not judged, nor is a storage class of no registered driver's ancestry (a private subclass of DBIO::Storage::DBI set as "storage_type" by hand). A related family is none of the two: a schema declaring MySQL connected through DBD::MariaDB is fine.

Settable on the schema class and on a connected schema; the storage reads it when it has something to report ("_driver_mismatch" in DBIO::Storage::DBI). A storage a driver builds without a schema (a writer or bulk storage) reads the switches of the schema of the storage it was built from.

This is an accessor of the schema, not a connect attribute: it is refused in the attributes of connect, and the error names the accessor.

package My::Schema;
use DBIO 'Schema', -pg;
__PACKAGE__->driver_strict(1);

driver_warnings

Arguments: boolean
Default value: true

Whether a declared driver that does not fit what it meets warns (see "driver_strict" for what is reported). Set it to false to silence these warnings; "driver_strict" turns them into errors and wins over this. Like "driver_strict" it is a schema accessor and no connect attribute.

exception_action

Arguments: $code_reference
Return Value: $code_reference
Default value: None

When "throw_exception" is invoked and "exception_action" is set to a code reference, this reference will be called instead of "throw" in DBIO::Exception, with the exception message passed as the only argument.

Your custom throw code must rethrow the exception, as "throw_exception" is an integral part of DBIO's internal execution control flow.

Example:

package My::Schema;
use DBIO 'Schema', -pg;
use My::ExceptionClass;
__PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
__PACKAGE__->load_classes;

# or:
my $schema_obj = My::Schema->connect( .... );
$schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });

stacktrace

Arguments: boolean

Whether "throw_exception" should include stack trace information. Defaults to false normally, but defaults to true if $ENV{DBIO_TRACE} is true.

The trace shows every live frame with its arguments, and a schema is connected by handing it the password as an argument. The password is not part of the trace: it is shown as *** in "connect" and "connection" -- in whichever class's connection the frame is -- and wherever an argument of another frame repeats it, in the frames of your own code that called "connect" too. So is a password inside an argument -- the value of a password, passwd, pwd or pass key, or the password of a URI, in a DSN first of all -- as in the messages about a connection ("connect_info" in DBIO::Storage::DBI). The frames, the files and lines, the rest of the DSN, the user name and every other argument stay as they are.

What is masked is what DBIO can find in the arguments of the live frames: the arguments of "connect" and "connection", and a dbi: DSN followed by a user name and a password in any other frame. A password that reaches DBIO in no argument -- from a DBIO::AccessBroker, a connection coderef or the environment -- and that your own code passes around as an argument is not known to it, nor is one your code holds in another shape than the one it connects with. A trace "throw_exception" writes also masks the password the schema's storage holds from connect_info, in any frame; it is read from the storage as it is, and no AccessBroker is asked for it. As in a message, a password is masked wherever an argument repeats it, however short it is; one that is also the user name masks that too. And every argument is looked through, whatever it holds: an SQL statement among them reads password = *** where it said password = ?.

All of this is about the trace DBIO writes. A trace Carp writes of its own accord -- every croak under $Carp::Verbose (perl -MCarp=verbose), or a confess in code that is not DBIO's -- is not built by DBIO ("masked_longmess" in DBIO::Util builds its own) and shows its arguments as Carp does. Where DBIO hands such a text on with the connect info at hand -- the DBI Connection failed exception of a connection that cannot be opened, DBI's own error after it -- the password is masked in it as well, escaped or shortened as Carp shows an argument.

sqlt_deploy_hook

Arguments: $sqlt_schema

An optional sub which you can declare in your own Schema class that will get called during deployment of the schema via "deploy".

DEPRECATED: This hook was designed for the legacy SQL::Translator deploy path and is a no-op in core DBIO. "deployment_statements" reads a pre-existing DDL file or throws, so nothing invokes it generically; it fires only if your storage's native Deploy class chooses to invoke it. It is retained for API compatibility.

For an example of what you can do with this, see "Adding Indexes And Functions To Your SQL" in DBIO::Manual::Cookbook.

If you want to execute post-deploy statements which can not be generated automatically, the currently suggested method is to overload "deploy" and use dbh_do.

class

Arguments: $source_name
Return Value: $classname
my $class = $schema->class('CD');

Retrieves the Result class name for the given source name.

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). Equivalent to calling $schema->storage->txn_do. See "txn_do" in DBIO::Storage for more information.

This interface is preferred over using the individual methods "txn_begin", "txn_commit", and "txn_rollback" below.

WARNING: If you are connected with AutoCommit => 0 the transaction is considered nested, and you will still need to call "txn_commit" to write your changes when appropriate. You will also want to connect with auto_savepoint => 1 to get partial rollback to work, if the storage driver for your database supports it.

Connecting with AutoCommit => 1 is recommended.

txn_scope_guard

Runs txn_scope_guard on the schema's storage. See "txn_scope_guard" in DBIO::Storage.

txn_begin

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

txn_commit

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

txn_rollback

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

storage

my $storage = $schema->storage;

Returns the DBIO::Storage object for this Schema. Grab this if you want to turn on SQL statement debugging at runtime, or set the quote character. For the default storage, the documentation can be found in DBIO::Storage::DBI.

populate

Arguments: $source_name, [ \@column_list, \@row_values+ ] | [ \%col_data+ ]
Return Value: \@result_objects (scalar context) | @result_objects (list context)

A convenience shortcut to "populate" in DBIO::ResultSet. Equivalent to:

$schema->resultset($source_name)->populate([...]);
NOTE

The context of this method call has an important effect on what is submitted to storage. In void context data is fed directly to fastpath insertion routines provided by the underlying storage (most often "execute_for_fetch" in DBI), bypassing the new and insert calls on the Result class, including any augmentation of these methods provided by components. For example if you are using something like DBIO::UUIDColumns to create primary keys for you, you will find that your PKs are empty. In this case you will have to explicitly force scalar or list context in order to create those values.

connection

Arguments: @args
Return Value: $new_schema

Similar to "connect" except sets the storage object and connection data in-place on the Schema class. You should probably be calling "connect" to get a proper Schema object instead.

A schema always has a driver

A schema whose "storage_type" resolves to the generic DBIO::Storage::DBI declares no driver, and connection throws before any storage is built, naming the schema class and the ways to declare one (ADR 0067). This holds for every schema class, also one made with use base 'DBIO::Schema', with or without sources. There is no warning mode and no guess from the DSN.

Overloading

Overload connection to change the behaviour of connect.

The skills key

A skills key in a hashref among the arguments is not a connection setting: connection takes it out of that hashref and stores it as this schema instance's skill overrides (see "skill"). The hashref is the caller's own and is changed in place, so the key is gone from it afterwards; pass a copy if the same hashref is used for another connection.

register_storage_layer

Arguments: $layer_class
Return Value: $self
__PACKAGE__->register_storage_layer('MyExt::Storage::Layer');

Register a storage extension layer package for this schema. On "connection" the registered layers are composed over the resolved base storage class (and, on driver rebless, re-composed over the concrete driver class) into a single synthesised class -- see DBIO::Storage::Composed. A layer is a plain method package that overrides or wraps the documented public storage surface, chaining with $self->next::method(@_); it MUST NOT use base a driver storage.

Callable on the class or on a connected instance -- an extension typically calls it from its own connection() override (before $self->next::method), mirroring how a driver component sets storage_type.

Registration is append-only and order-preserving, de-duplicated by class name (connection() may run more than once). Because storage_layers is inherited class data whose default empty arrayref is shared across subclasses, this method builds a fresh arrayref (copy plus the new layer) and sets it back on the caller, so a registration never leaks into a parent or sibling schema class.

Precedence: registration order is C3 precedence. The first layer registered becomes the most-specific rung of the composed @ISA, so its methods win the MRO and its next::method reaches the next layer, then the base -- consistent with load_components, where the first-loaded component runs first.

compose_namespace

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

For each DBIO::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 DBIO::ResultSource object to the new $schema object. If $additional_base_class is given, the new composed classes will inherit from first the corresponding class 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

svp_begin

Creates a new savepoint (throws an exception outside a transaction). Equivalent to calling $schema->storage->svp_begin. See "svp_begin" in DBIO::Storage for more information.

svp_release

Releases a savepoint (throws an exception outside a transaction). Equivalent to calling $schema->storage->svp_release. See "svp_release" in DBIO::Storage for more information.

svp_rollback

Rollback to a savepoint (throws an exception outside a transaction). Equivalent to calling $schema->storage->svp_rollback. See "svp_rollback" in DBIO::Storage for more information.

clone

Arguments: %attrs?
Return Value: $new_schema

Clones the schema and its associated result_source objects and returns the copy. The resulting copy will have the same attributes as the source schema, except for those attributes explicitly overridden by the provided %attrs.

throw_exception

Arguments: $message

Throws an exception. Obeys the exemption rules of DBIO::Carp to report errors from outer-user's perspective. See "exception_action" for details on overriding this method's behavior. If "stacktrace" is turned on, throw_exception's default behavior will provide a detailed stack trace.

deploy

Arguments: \%sqlt_args, $dir

Deploys the schema to the current storage. If the storage class provides a native Deploy class (via its dbio_deploy_class hook), uses that. The native path takes the option add_drop_table out of \%sqlt_args (the declared views and tables are dropped, in the same batch, before the install DDL) and refuses every other key, version included -- the native install always installs the current state of the schema -- by throwing ("deploy_args" in DBIO::Deploy::Base); it ignores $dir. Otherwise falls back to the storage's deploy, handing it \%sqlt_args and $dir: DBIO::Storage::DBI runs the statements of an existing DDL file in $dir (default ./, named by "ddl_filename") and throws if there is no such file -- it does not generate DDL (see "deployment_statements" in DBIO::Storage::DBI). $storage->deploy routes to the native Deploy class itself, so calling it directly installs the same way.

deployment_statements

Arguments: See "deployment_statements" in DBIO::Storage::DBI
Return Value: $listofstatements

A convenient shortcut to $self->storage->deployment_statements($self, @args). Returns the contents of the existing DDL file named for these arguments (see "ddl_filename") and throws when there is none. It does not generate SQL; "deploy" installs through the storage's native Deploy class and falls back to this file only when the storage has none.

create_ddl_dir

Arguments: See "create_ddl_dir" in DBIO::Storage::DBI

DEPRECATED: This method is deprecated and throws an exception if called. Generate and apply DDL through the storage's native Deploy class instead (see "deploy" in DBIO::Schema).

A convenient shortcut to $self->storage->create_ddl_dir($self, @args), which historically created an SQL file based on the Schema for each of the specified database types.

ddl_filename

Arguments: $database-type, $version, $directory, $preversion
Return Value: $normalised_filename
my $filename = $schema->ddl_filename($type, $version, $dir, $preversion)

This method is called by "deployment_statements" in DBIO::Storage::DBI to compose the name of the DDL file it reads, out of the supplied directory, database type and version number. The default file name format is: $dir$schema-$version-$type.sql.

You may override this method in your schema if you wish to use a different format.

thaw

Provided as the recommended way of thawing schema objects. You can call Storable::thaw directly if you wish, but the thawed objects will not have a reference to any schema, so are rather useless. Thaw only data of your own, from a source you trust: Storable creates objects of whatever class the data names. The classes of a thawed source are checked against the result classes of the sources registered on this schema.

freeze

This doesn't actually do anything beyond calling nfreeze, it is just provided here for symmetry.

dclone

Arguments: $object
Return Value: dcloned $object

Recommended way of dcloning DBIO::Row and DBIO::ResultSet objects so their references to the schema object (which itself is not cloned) are properly maintained. Clone only your own objects: dclone goes through the same Storable thaw as "thaw".

schema_version

Returns the current schema class' $VERSION in a normalised way.

register_class

Arguments: $source_name, $component_class

This method is called by "load_namespaces" and "load_classes" to install the found classes into your Schema. You should be using those instead of this one.

You will only need this method if you have your Result classes in files which are not named after the packages (or all in the same file). You may also need it to register classes at runtime.

Registers a class which isa DBIO::ResultSourceProxy. Equivalent to calling:

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

register_source

Arguments: $source_name, $result_source

This method is called by "register_class".

Registers the DBIO::ResultSource in the schema with the given source name.

unregister_source

Arguments: $source_name

Removes the DBIO::ResultSource from the schema for the given source name.

register_extra_source

Arguments: $source_name, $result_source

As "register_source" but should be used if the result class already has a source and you want to register an extra one.

AUTHOR

DBIO & DBIx::Class Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.

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