This is a second post of a series about DBIx::Perlish Perl module.

Let us go through the example of DBIx::Perlish's non-SQL language which I concluded the last post with:

my $uid = 42;
my @r = db_fetch {
    my $u : users;

    $u->groups_id == groups->id;
    $u->id == $uid;
};

I hope it is obvious to you what that snippet does, but let's go through it anyway.

First thing to note that it deals with two database tables, users and groups. The snippet also illustrates that there are two ways to refer to a table - explicitly by name, as is done with groups, and via aliasing a table to a local variable using Perl attribute syntax. This latter method is preferable when you have to refer to a table more than once or twice. This method is also the only one with which you can make self-joins, but I'll talk about it later.

So the above snippet could have been written as

my $uid = 42;
my @r = db_fetch {
    users->groups_id == groups->id;
    users->id == $uid;
};

as well as

my $uid = 42;
my @r = db_fetch {
    my $u : users;
    my $g : groups;

    $u->groups_id == $g->id;
    $u->id == $uid;
};

There are more things to pay attention to in the example.

You refer to the individual columns using Perl method call syntax. Since it is common to use accessor methods with Perl objects in order to get or set their properties, it does not require a stretch of imagination to see what $u->groups_id means.

The declarative semantics of the language is apparent in how you specify what results you want back from the query: individual comparison expressions are used as filters to limit an unconstrained result.

Let's look at a simpler example:

my @r = db_fetch {
   my $u : users;
}

This will get you all rows from the users table. If you only want users with an id over a hundred, you would write:

my @r = db_fetch {
   users->id > 100;
}

If you were operating with a normal Perl array instead of a DB table, you would probably do the same filtering in one of two ways, a more familiar imperative one:

my @r;
for my $u (@users) {
   push @r, $u if $u->{id} > 100;
}

or a shorter declarative one, using grep:

my @r = grep { $_->{id} > 100 } @users;

So how the query language is used resembles declarative grep more than imperative for. But it is not news to you - after all, SQL does precisely the same!

More to follow.