DBIx::C...::Schema(3)

πŸ’– NAME πŸ’–

okay so this is the DBIx::C...::Schema(3) page β€” aka DBIx::Class::Schema β€” and it's literally composable schemas, bestie. Yes, it's a User Contributed Perl Documentation page, and it's about to eat. 🫢

🌸 SYNOPSIS 🌸

         package Library::Schema;
         use base qw/DBIx::Class::Schema/;

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

         package Library::Schema::Result::CD;
         use base qw/DBIx::Class::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( ... );

πŸ’… DESCRIPTION πŸ’…

So this module creates database classes based on a schema. It's the recommended way to use DBIx::Class, and it lets you use more than one concurrent connection with your classes. iconic behavior, honestly. ✨

NB: if you're used to Class::DBI, please read the SYNOPSIS carefully β€” DBIx::Class does things a little differently. Pay special attention to which module inherits off which, bestie. πŸ‘€

πŸŽ€ 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::*. slay. πŸ’…

ResultSet classes are associated with the Result class of the same name. So My::Schema::Result::CD will get the ResultSet class My::Schema::ResultSet::CD if it is present. matching outfits, basically. πŸŽ€

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". iykyk. ⭐

⚠️ 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' for '$result_class', but it seems
         that you had already set '$result_class' to use '$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. highkey useful. πŸ¦‹

         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, and both of them 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. periodt. πŸ’…

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. not me forgetting that. 😭

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 DBIC 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: DBIx::Class::Storage::DBI

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

You want to use this to set subclasses of DBIx::Class::Storage::DBI in cases where the appropriate subclass is not autodetected.

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 DBIx::Class::Storage::DBI::Replicated for an example of this. 🫢

πŸ¦‹ 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 DBIx::Class::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 DBIC's internal execution control flow. no cap, this one matters. πŸ”₯

Example:

          package My::Schema;
          use base qw/DBIx::Class::Schema/;
          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{DBIC_TRACE} is true. vibe check passed. ⭐

πŸ‘‘ sqlt_deploy_hook

Arguments: $sqlt_schema

An optional sub which you can declare in your own Schema class that will get passed the SQL::Translator::Schema object when you deploy the schema via create_ddl_dir or deploy.

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

Note that sqlt_deploy_hook is called by deployment_statements, which in turn is called before deploy. Therefore the hook can be used only to manipulate the SQL::Translator::Schema object before it is turned into SQL fed to the database. If you want to execute post-deploy statements which can not be generated by SQL::Translator, the currently suggested method is to overload deploy and use dbh_do. bestie, that's the whole setup section. πŸ’–

πŸ’– METHODS πŸ’–

🌟 connect

Arguments: @connectinfo Return Value: $new_schema

Creates and hands you back a brand-new Schema object, bestie. The connection info you set on it gets used to spin up a fresh instance of the storage backend, and that gets set on the Schema object. It's giving "new phone who dis" but for databases. ✨

Peep "connect_info" in DBIx::Class::Storage::DBI for the DBI-specific tea on the @connectinfo argument, or DBIx::Class::Storage in general if you want the big picture.

Heads up! connect_info expects an arrayref of arguments, but connect does not. connect is nice like that β€” it wraps its args in an arrayref for you before passing them along to connect_info. πŸŽ€

Overloading

connect is literally just a convenience method. It's equivalent to calling $schema->clone->connection(@connectinfo). So if you wanna write your own overloaded version, overload connection instead, not this one. iykyk πŸ’…


🌟 resultset

Arguments: $source_name Return Value: $resultset

my $rs = $schema->resultset('DVD');

Returns the DBIx::Class::ResultSet object for the registered source name. Your fave little query-machine, ready to go. πŸ¦‹


🌟 sources

Return Value: @source_names

my @source_names = $schema->sources;

Lists out the names of all the sources registered on this Schema object. Like a guest list, but for your tables. πŸ‘‘


🌟 source

Arguments: $source_name Return Value: $result_source

my $source = $schema->source('Book');

Returns the DBIx::Class::ResultSource object for the registered source name. That's the source object itself, not the resultset β€” different vibe, both iconic. πŸ’œ


🌟 class

Arguments: $source_name Return Value: $classname

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

Grabs you the Result class name for the given source name. Just the name, bestie β€” a string, not the object. πŸŽ€


🌟 txn_do

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

Runs $coderef with the (optional) arguments @coderef_args atomically, and returns its result (if it even has one). Equivalent to calling $schema->storage->txn_do. See "txn_do" in DBIx::Class::Storage for the full lore.

This interface is preferred over using the individual methods txn_begin, txn_commit, and txn_rollback down below. Level up, don't downgrade. ✨

WARNING: if you're connected with AutoCommit => 0, the transaction is considered nested, and you'll still need to call txn_commit to actually write your changes when appropriate. You'll also wanna connect with auto_savepoint => 1 if you want partial rollback to work β€” assuming the storage driver for your database even supports it. 😭

Connecting with AutoCommit => 1 is recommended. Do that instead, fr fr. πŸ’…


🌟 txn_scope_guard

Runs txn_scope_guard on the schema's storage. See "txn_scope_guard" in DBIx::Class::Storage for more. 🫢


🌟 txn_begin

Begins a transaction β€” and does nothing if AutoCommit is off, just so you know. Equivalent to calling $schema->storage->txn_begin. See "txn_begin" in DBIx::Class::Storage for more info. 🌈


🌟 txn_commit

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


🌟 txn_rollback

Rolls back the current transaction. Equivalent to calling $schema->storage->txn_rollback. See "txn_rollback" in DBIx::Class::Storage for more. It's giving ctrl+z energy. πŸ’€


🌟 storage

my $storage = $schema->storage;

Returns the DBIx::Class::Storage object for this Schema. Grab this if you wanna turn on SQL statement debugging at runtime, or set the quote character. For the default storage, the docs live in DBIx::Class::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 DBIx::Class::ResultSet. Equivalent to:

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

NOTE

The context of this method call has a big effect on what actually gets submitted to storage, bestie β€” pay attention:

  • In void context, data gets fed directly to the 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're using something like DBIx::Class::UUIDColumns to create primary keys for you, you'll find that your PKs are empty. In this case you'll have to explicitly force scalar or list context in order to create those values.

So yeah β€” void context is a speedrun, and sometimes it skips the important stuff. πŸ™ˆ


🌟 connection

Arguments: @args Return Value: $new_schema

Similar to connect, except it 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, ngl.

Overloading

Overload connection to change the behaviour of connect. That's the whole trick. πŸ’…


🌟 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's literally making clones but with new surnames. πŸ‘‘

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 class from the current schema, then the base class. Order matters, bestie. ✨

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

Look at that inheritance tree slaying. 🌸


🌟 svp_begin

Creates a new savepoint β€” and does nothing outside a transaction. Equivalent to calling $schema->storage->svp_begin. See "svp_begin" in DBIx::Class::Storage for more. πŸŽ€


🌟 svp_release

Releases a savepoint β€” and again, does nothing outside a transaction. Equivalent to calling $schema->storage->svp_release. See "svp_release" in DBIx::Class::Storage for more. 🫢


🌟 svp_rollback

Rolls back to a savepoint β€” and yep, does nothing outside a transaction. Equivalent to calling $schema->storage->svp_rollback. See "svp_rollback" in DBIx::Class::Storage for more. Rewind time, but make it legal. βͺ


🌟 clone

Arguments: %attrs? Return Value: $new_schema

Clones the schema and its associated result_source objects, then returns the copy. The resulting copy will have the same attributes as the source schema β€” except for those attributes explicitly overridden by the %attrs you pass in. Customize your clone, bestie. 🧚


🌟 throw_exception

Arguments: $message

Throws an exception. It obeys the exemption rules of DBIx::Class::Carp so errors get reported from the outer-user's perspective β€” which is way nicer for debugging, trust. See "exception_action" for details on overriding this method's behavior. And if "stacktrace" is turned on, throw_exception's default behavior will provide a detailed stack trace. πŸ“š


🌟 deploy

Arguments: \%sqlt_args, $dir

Attempts to deploy the schema to the current storage using SQL::Translator. Big moment. πŸš€

See "METHODS" in SQL::Translator for a list of values for \%sqlt_args. The most common value for this would be { add_drop_table => 1 }, so the SQL produced includes a DROP TABLE statement for each table created. For quoting purposes, supply quote_identifiers.

Additionally, the DBIx::Class parser accepts a sources parameter as a hash ref or an array ref, containing a list of sources to deploy. If present, then only the sources listed will get deployed. And check this β€” you can use the add_fk_index parser parameter to stop the parser from creating an index for each FK. πŸ’…

Careful: deploying can run DROP TABLE statements if you ask it to. That's destructive energy β€” make sure that's what you actually want. πŸ’€

🌟 deployment_statements

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

A convenient shortcut to $self->storage->deployment_statements($self, @args). Returns the statements used by deploy and "deploy" in DBIx::Class::Storage. It's the receipts for your deploy. 🧾


🌟 create_ddl_dir

Arguments: See "create_ddl_dir" in DBIx::Class::Storage::DBI

A convenient shortcut to $self->storage->create_ddl_dir($self, @args).

Creates an SQL file based on the Schema, for each of the specified database types, in the given directory. Batch-generated DDL, we love to see it. ✨


🌟 ddl_filename

Arguments: $database-type, $version, $directory, $preversion Return Value: $normalised_filename

my $filename = $table->ddl_filename($type, $version, $dir, $preversion)

This method gets called by create_ddl_dir to compose a file name 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 wanna use a different format. Go off, customize. πŸŽ€

WARNING Prior to DBIx::Class version 0.08100, this method had a different signature: perl my $filename = $table->ddl_filename($type, $dir, $version, $preversion) In recent versions, the variables $dir and $version were reversed in order to bring the signature in line with other Schema/Storage methods. If you really need to maintain backward compatibility, you can do the following in any overriding methods: perl ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100); Time travel is possible, bestie. Just check your version first. πŸ’€

🌟 thaw

Provided as the recommended way of thawing schema objects. You can call Storable::thaw directly if you wish, but the thawed objects won't have a reference to any schema, so they're pretty much useless. Like an unlocked phone. πŸ“΅


🌟 freeze

This doesn't actually do anything beyond calling nfreeze β€” it's just provided here for symmetry. Aesthetic-only method. πŸ’…


🌟 dclone

Arguments: $object Return Value: dcloned $object

The recommended way of dcloning DBIx::Class::Row and DBIx::Class::ResultSet objects, so that their references to the schema object (which itself is not cloned) are properly maintained. Keep those ties strong, fr fr. 🫢


🌟 schema_version

Returns the current schema class' $VERSION in a normalised way. Cute and tidy. πŸŽ€


🌟 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 β€” this is the backstage crew, not the main character. πŸ‘‘

You'll 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. Edge cases, but they happen. 🌈

Registers a class which isa DBIx::Class::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. The circle of life continues. πŸ¦‹

Registers the DBIx::Class::ResultSource in the schema with the given source name. πŸŽ€


🌟 unregister_source

Arguments: $source_name

Removes the DBIx::Class::ResultSource from the schema for the given source name. Bye bestie, you're off the guest list. πŸ‘‹


🌟 register_extra_source

Arguments: $source_name, $result_source

Same as register_source, but use this one if the result class already has a source and you want to register an extra one. Bonus round. ✨


🌟 compose_connection (DEPRECATED)

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

DEPRECATED. You probably wanted compose_namespace. 😭

Actually... you probably just wanted to call connect. Do that instead, bestie. πŸ’…


πŸ’– FURTHER QUESTIONS? πŸ’–

okay so if you're sitting there like "bestie i still have questions" β€” literally same, that's so valid 🫢. Go check out the list of additional DBIC resources. That's the move. No cap, that's where the extra lore lives ✨.


the legal tea, served fresh β˜•πŸ’…:

  • this module is free software, copyright by the DBIx::Class (DBIC) authors πŸ‘‘
  • you can redistribute it and/or modify it under the same terms as the DBIx::Class library πŸ“œ

that's it, that's the whole vibe. go forth and slay πŸ”₯πŸ¦‹


and that's a wrap on the whole page, bestie!! πŸŽ‰πŸŒΈ you made it to the very end, iconic behavior fr fr πŸ’œ. this lil masterpiece is from perl v5.42.0, dated 2025-01-22 β€” so yeah, she's got a timestamp and everything πŸ’…βœ¨. now go write some schemas, you absolute main character πŸŒˆπŸ‘‘

πŸ“¦ where this page comes from