DBIx::Class vs DBIO

3 min read
← Back to Blogs
DBIx::Class vs DBIO

DISCLAIMER: Image is generated using ChatGPT.



While I have been writing the manuscript for my upcoming book on DBIx::Class, I must admit that I haven’t dedicated all of my focus to it. Everywhere I look I see something new and interesting and have been easily distracted. For example, just the other day I noticed that there is a new player in the Perl ORM space named DBIO.

If you are not familiar with what I am talking about, I suggest that you take a moment to investigate DBIO more closely.

At first blush, it appears that installing DBIO is not easy, as I had to force my way through the installation process. I do not have enough time or effort at this moment to research why I was unable to complete the installation successfully. However, given that I am currently working on a book about DBIx::Class and the fact that this project is similar to DBIx::Class, I thought it was only fitting that I report the results of my installation attempt to the DBIx::Class community.

In addition, I plan to cover my project, DBIx::Class::Async, in a chapter within the manuscript of my book. Although it is exciting to add additional content to consider for the manuscript; it is also causing me to push the release date of the book further away.

In this post, I will write some of the standard examples that are provided in DBIC using DBIO to see how closely they resemble each other.

Let’s assume we have this table structure:

CREATE TABLE author (
    id   INTEGER PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE book (
    id        INTEGER PRIMARY KEY,
    author_id INTEGER REFERENCES author(id),
    title     VARCHAR(255) NOT NULL
);

I have the following folder structure:

├── lib
│   └── MyApp
│       ├── DBIO
│       │   └── Result
│       │       ├── Author.pm
│       │       └── Book.pm
│       ├── DBIO.pm
│       ├── Schema
│       │   └── Result
│       │       ├── Author.pm
│       │       └── Book.pm
│       └── Schema.pm
└── t
    ├── dbic.t
    └── dbio.t

Using DBIx::Class



File: lib/MyApp/Schema.pm

package MyApp::Schema;

use strict;
use warnings;
use base 'DBIx::Class::Schema';

__PACKAGE__->load_namespaces;

1;

File: lib/MyApp/Schema/Result/Author.pm

package MyApp::Schema::Result::Author;

use strict;
use warnings;
use base 'DBIx::Class::Core';

__PACKAGE__->table('author');
__PACKAGE__->add_columns(
    id   => { data_type => 'integer', is_auto_increment => 1 },
    name => { data_type => 'varchar', size => 255 },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(books => 'MyApp::Schema::Result::Book', 'author_id');

1;

File: lib/MyApp/Schema/Result/Book.pm

package MyApp::Schema::Result::Book;

use strict;
use warnings;
use base 'DBIx::Class::Core';

__PACKAGE__->table('book');
__PACKAGE__->add_columns(
    id        => { data_type => 'integer', is_auto_increment => 1 },
    author_id => { data_type => 'integer' },
    title     => { data_type => 'varchar', size => 255 },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to(author => 'MyApp::Schema::Result::Author', 'author_id');

1;

Using DBIO



Let’s re-create the same using DBIO now.

File: lib/MyApp/DBIO.pm

package MyApp::DBIO;

use strict;
use warnings;
use base 'DBIO::Schema';

__PACKAGE__->load_namespaces;

1;

File: lib/MyApp/DBIO/Author.pm

package MyApp::DBIO::Result::Author;

use strict;
use warnings;
use base 'DBIO::Core';

__PACKAGE__->table('author');
__PACKAGE__->add_columns(
    id   => { data_type => 'integer', auto_nextval => 1 },
    name => { data_type => 'varchar', size => 255 },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(books => 'MyApp::DBIO::Result::Book', 'author_id');

1;

File: lib/MyApp/DBIO/Result/Book.pm

package MyApp::DBIO::Result::Book;

use strict;
use warnings;
use base 'DBIO::Core';

__PACKAGE__->table('book');
__PACKAGE__->add_columns(
    id        => { data_type => 'integer', auto_nextval => 1 },
    author_id => { data_type => 'integer' },
    title     => { data_type => 'varchar', size => 255 },
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to(author => 'MyApp::DBIO::Result::Author', 'author_id');

1;

Now that have laid down the foundation, time to create unit test.

File: t/dbic.t

#!/usr/bin/perl

use strict;
use warnings;
use Test::More;

use_ok('MyApp::Schema');

my $schema = MyApp::Schema->connect('dbi:SQLite:dbname=:memory:');
$schema->deploy();

pass("Deployed DBIx::Class schema successfully");

my $author = $schema->resultset('Author')->create({
    id => 1, name => 'J.R.R. Tolkien' });

my $book = $author->create_related('books', {
    id => 101, title => 'The Hobbit' });

isa_ok($book,
       'MyApp::Schema::Result::Book',
       'Created book instance');

my $fetched_book = $schema->resultset('Book')->find(101);
is($fetched_book->author->name,
   'J.R.R. Tolkien',
   'belongs_to relationship correctly resolved the author name');

done_testing;

File: t/dbio.t

!/usr/bin/perl

use strict;
use warnings;
use Test::More;

use_ok('MyApp::DBIO');

my $dbio = MyApp::DBIO->connect('dbi:SQLite:dbname=:memory:');
$dbio->deploy();
pass("Deployed DBIO schema successfully");

my $author = $dbio->resultset('Author')->create({
    id => 1, name => 'George R.R. Martin' });

my $book = $author->create_related('books', {
    id => 201, title => 'A Game of Thrones' });

isa_ok($book,
       'MyApp::DBIO::Result::Book',
       'Created DBIO book instance');

my $fetched_book = $dbio->resultset('Book')->find(201);
is($fetched_book->author->name,
   'George R.R. Martin',
   'DBIO relationship correctly resolved');

done_testing;

Nothing ground breaking, just scratched the surface.

Time for final testing:

$ yath
PERL_HASH_SEED not set, setting to '20260624' for more reproducible results.

** Defaulting to the 'test' command **

( PASSED )  job  1    t/dbic.t
( PASSED )  job  2    t/dbio.t

                                Yath Result Summary
-----------------------------------------------------------------------------------
     File Count: 2
Assertion Count: 8
      Wall Time: 1.28 seconds
       CPU Time: 1.02 seconds (usr: 0.13s | sys: 0.03s | cusr: 0.67s | csys: 0.19s)
      CPU Usage: 79%
    -->  Result: PASSED  <--

What is yath?

In case you missed it, I wrote a blog post on the topic. Please take a look: Testing in Perl.



Happy Hacking !!!