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.