The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

DBIx::Inline - DBIx::Class without the class.

DESCRIPTION

This module is yet another interface to DBI. I like how DBIx::Class works, separating the results from the resultsets, the resultsets from the results and the schema from everything else. It's tidy, easy to follow and works a treat. I also like how you can "reuse" queries in resultsets and results without typing them out again and again. However, when I wanted to work on a small project I found DBIx::Class a little slow and didn't want to keep setting up the classes for it to work. DBIx::Inline attempts follow the way DBIx::Class does things, but more "inline". You still get the reusable queries, Results and ResultSets, but without all the classes to setup. You do lose a lot of functionality that you get with DBIx::Class, but that's not what DBIx::Inline is really about. I wanted it to be faster and not hold your hand with everything, yet still be easy enough to use. It's still possible to have accessors and Result/ResulSet methods, but they are created on-the-fly with method. Also, you can automatically create all accessors for a result using load_accessors. DBIx::Inline is great for small projects that do not require a lot of customisation, but for anything else I'd highly recommend DBIx::Class.

SYNOPSIS

package MyDB;

use base 'DBIx::Inline';

my $rs = MyDB->model('Foo')->all; # Read up about models to see what this does
# or..
my $rs = MyDB->sqlite('/some/sqlite.db')->resultset('users')->all;
# or..
my $rs = MyDB->connect(
    dbi => 'SQLite:/some/sqlite.db',
);
$rs = $rs->resultset('users');

# create a resultset method on-the-fly
$rs->method(not_active => sub {
    return shift->search([], { account_status => 'disabled' }, { order => ['id'], rows => 5 });
});

# chain the custom resultset method with a core one (count)
print "Rows returned: " . $rs->not_active->count . "\n";

# make the records in the resultset active
# will return a resultset with the updated data
my $new_rs = $rs->update({account_status => 'active'});

connect

Creates the Schema instance using the hash specified. Currently only dbi is mandatory, which tells DBI which engine to use (SQLite, Pg, etc). If you're using SQLite there is no need to set user or pass.

my $dbh = DBIx::Inline->connect(
    dbi => 'SQLite:/var/db/test.db',
);

my $dbh = DBIx::Inline->connect(
    dbi  => 'Pg:host=myhost;dbname=dbname',
    user => 'username',
    pass => 'password',
);

model

Models make your life easier when you need to reuse a specific connection. You can even go so far as specifying a ResultSet to use by default. By default, DBIx::Inline will look for inline.yml, unless you have configured a different models file with config('file.yml'). The syntax is very basic and uses a simple YAML file, making it easy to move around if you need to.

   # inline.yml
   ---
   Foo:
     connect: 'SQLite:foo.db'
   
   AnotherSchema:
     connect: 'Pg:host=localhost;dbname=foo'
     user: 'myuser'
     pass: 'pass'

   WithResultSet:
     connect: 'SQLite:test.db'
     table: 'users'
     columns: id name status date_created(datetime)

   # test.pl
   package main;
 
   my $rs = main->model('AnotherSchema')->resultset('the_table');
   my $rs2 = main->model('WithResultset'); # that's all we need!
   while(my $row = $rs2->next) {
       $row->load_accessors;
       print $row->name;
   }

As of 0.15 you can now use related tables. It basically does a search_join in a convenient accessor for you. The accessor search is *very* limited, allowing only one key.

# inline.yml
AnotherSchema:
  connect: 'Pg:host=localhost;dbname=foo'
  user: 'myuser'
  pass: 'pass'
  related:
    authors: 'id <-> books(authors_id)'

# then in your code
my $rs = $c->model('AnotherSchema')->resultset('authors');
my $books = $rs->authors({ id => 3 }); # search for all books by author with id of 3

# now use it as any normal resultset
while( my $row = $books->next ) {
    $row->load_accessors;
    print $row->book_title;
}

As of 0.17 you can now resuse a models connection.

 ---
 MainDB:
   connect: 'Pg:host=localhost;dbname=thisdb'
   user: 'foo'
   pass: 'bar'
 
 Author:
   model: MainDB
   resultset: authors
   related:
     authors: 'id <-> books(author_id)'

 BooK:
   model: MainDB
   table: books

0.19 offers the ability to add columns. Doing this will create an accessor to that result. You can even return a DateTime object on time results by adding (datetime) at the end of the column.

   ---
   Customer:
     model: MyModel
     table: customers
     columns: id name status date_created(datetime) suspended(datetime)

   # sql.pl
   package MyDB;

   my $customers = MyDB->model('Customer')->all;
   print $customers->last->date_created;      # prints DateTime object
   print $customers->last->date_created->ymd; # you can then call DateTime methods on the object

sqlite

Initially load a SQLite database (file). Instead of going through models or dbi string we can just call sqlite('file').

package main;

use base 'DBIx::Inline';

my $schema = main->sqlite('/path/to/db.db')->resultset('users');

config

Sets the location of the configuration (file with the models. The Schema models.. not girls). This allows you to have the file anywhere on your system and you can rename it to anything.

# /var/schema/myschemas.yml
Foo:
  connect: 'SQLite:/var/db/mydb.db'

# /scripts/db.pl
package main;

use base 'DBIx::Inline';

main->config ('/var/schema/myschemas.yml');
my $schema = main->model('Foo');

You can even chain config to model if you want.

my $schema = main->config('/var/schema/myschemas.yml')->model('Foo');

AUTHOR

Brad Haywood <brad@geeksware.net>

LICENSE

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