NAME

DBIx::Quick - Object Relational Mapping for the lazy programmer

SYNOPSIS

package MyApp::DAO::Users;

use strict;
use warnings;

use DBIx::Quick;

table 'users';

has dbh => (is => 'ro', required => 1);

field id => (is => 'ro', search => 1, pk => 1);
field username => (is => 'rw', search => 1, required => 1, column => 'user_name');
field id_address => (is => 'rw', search => 1, fk => ['MyApp::DAO::Addresses', 'id', 'addresses', 'users']);

fix;

And elsewhere:

my $user = MyApp::DAO::Users::Instance->new(username => 'lazybastard', id_address => 5);
my $dao = MyApp::DAO::Users->new(dbh => DBI->connect(...));
$dao->insert($user)
($user) = @{$dao->search(username => 'lazybastard')};
$user->username('lazyandproductive');
$dao->update($user, 'username');
$user = $user->fetch_again; 
$dao->delete($user);

DESCRIPTION

DBIx::Quick is the needed bridge between Moo and your database, you create DAO objects in a similar fashion to Moo and those objects auto-create the corresponding instances under the same package plus ::Instance, importing this module becomes your package into a Moo class and the created class is also a Moo one.

Many times writing object to relational database mapping you find yourself having to repeat the same information once and once again which becomes tiring for the developer, Models and DAO are created in a single step in a single file to prevent this, but they remain completely separate classes, methods are provided to take full advantage of the separation.

The Moo syntax also provides shorter code overall.

This module is preliminar, meaning the syntax is probably not the definitive one, if you are a programmer who wants to spend less effort into making full blown applications feel free to join the development with suggestions or patches.

If you are needing too fancy autocomplete or templates just to be productive maybe you instead need DBIx::Quick.

DAO DECLARATIONS

While declaring a DBIx::Quick mapping you can use the following subs autoimported into your package namespace.

table

table 'transactions';

Specify the table this DAO maps to.

field

field id => (is => 'ro', pk => 1, search => 1);
field amount => (is => 'ro', required => 1, search => 1, column => 'amnt');
field tax => (is => 'ro');
field id_user => (is => 'ro', required => 1, search => 1, fk => ['MyApp::DAO::Users', 'id', 'users', 'transactions']);

field is the equivalent to Moo has sub implementing all its options (useful or not) to represent a column into the table.

It provides the following extra options:

pk

Defines the primary key if sent a trueish value

Marks this column as searchable for the generated search method.

column

Allows to change the destination column by default it would be called as the field itself.

fk

Takes four arguments: The destination class, the destination field, the method to represent in our model the remote class and optionally the remote instance method to represent our own class.

fix

Ensures the class is ready to be used and marks the class as ready.

instance_sub

instance_sub uppercase_username => sub {
	my $self = shift;
	return uc($self->username);
};

and later:

$user->uppercase_username;

Declares a subroutine to be added to the generated ::Instance Object.

instance_has

 instance_has cache => (is => 'lazy');
 instance_sub _build_cache => sub {
 	my $redis = Redis->new;
	return $redis;
 };

Makes a Moo attribute available to the ::Instance Object with the same syntax than Moo has.

dbh

You must declare a dbh method or a Moo attribute returning a DBI connection.

DAO METHODS

search

 my @transactions = @{$dao->search(
	# SQL::Abstract::More where syntax using field names instead of columns
 	amnt => { '>', 10000 },
 	tax  =>	21,
 )}

Searchs ::Instance Objects in the table using SQL::Abstract::More where syntax but replacing the column names by field names.

my @transactions = @{$dao->free_search(
	-join => [
		'users.id=transactions.id_user users',
	],
       -where => {
		'users.surname' => {-like => 'Gar%},
	},
)};

Searchs ::Instance Objects in the table using all the syntax of SQL::Abstract::More select, columns are the real columns not fields.

-columns and -from are not allowed to be used. -from should be substituted by -join and -columns is not needed.

insert

$dao->insert(MyApp::DAO::Users::Instance->new(username => 'ent'));

Inserts a row in the table, doesn't return the inserted field. You can use UUIDs or other known unique attributes of the table to search for the inserted object.

update

$user->username('X');
$user->surname('González');
$dao->update($user, 'username', 'surname');

Takes an instance and a list of the fields that should be updated in db with the instance data for that row, updates them and doesn't have a meaningful return. Searches the object to update by the primary key.

delete

$dao->delete($user);

Vanishes the instance of the database. Searches by the primary key.

BUGS AND LIMITATIONS

Every DAO/Instance must be associated directly with a table, if you need something extra, the good old and reliable SQL::Abstract::More is enough to you.

Errors must be improved to allow users to debug easier faulty code.

API is not stable since this program is so early in its development that I do not know if incorrect assumptions or bad design is hiding here.

No many to many easy wrapper, use free_search, I could not come up with something that would be better than directly creating your own queries with free_search.

AUTHOR

SERGIOXZ - Sergio Iglesias

CONTRIBUTORS

SERGIOXZ - Sergio Iglesias

COPYRIGHT

Copyright © Sergio Iglesias (2025)

LICENSE

This library is free software and may be distributed under the same terms as perl itself. See https://dev.perl.org/licenses/.