SELECT * FROM users,groups
WHERE
users.groups_id = groups.id AND
users.id = 42;
Within Perl program, SQL is a Domain-Specific Language.
Within Perl program, SQL is a Domain-Specific Language.
A *LARGE* one.
Switching back and forth is difficult.
Disrupts program flow
my $r = $dbh->selectall_arrayref(
"SELECT * FROM users, groups
WHERE
users.groups_id = groups.id AND
users.id = ?",
{Slice=>{}}, 42);
Object-relational mappers.
Replace DSL SQL with *another* DSL.
...which looks like Perl.
my $uid = 42;
my @r = db_fetch {
my $u : users;
$u->groups_id == groups->id;
$u->id == $uid;
};
my $uid = 42;
my @r = db_fetch {
my $u : users;
my $g : groups;
$u->groups_id == $g->id;
$u->id == $uid;
};
my $uid = 42;
my @r = db_fetch {
users->groups_id == groups->id;
users->id == $uid;
};
$object->method;
$table->column;
my @r = db_fetch {
my $u : users;
}
my @r = db_fetch {
users->id > 100;
}
my @r;
for my $u (@users) {
push @r, $u if $u->{id} > 100;
}
my @r = grep { $_->{id} > 100 } @users;
my $uid = 42;
my @r = db_fetch {
my $u : users;
$u->groups_id == groups->id;
$u->id == $uid;
};
my $uid = 40;
my @r = db_fetch {
users->id == $uid + 2;
};
my @r = db_fetch {
my $u : users;
return $u->first_name . " " . $u->last_name;
};
my @r = db_fetch {
my $u : users;
return "$u->first_name $u->last_name";
};
No return == "SELECT *"
Use return if you want control of what is returned
Context determines how many *rows* you want:
"Return" determines how many *columns* you want:
my $name = db_fetch { return user->name };
print "The name of some user is $name\n";
my @names = db_fetch { return user->name };
print "The names of all users are @names\n";
my $u = db_fetch { return user->id, user->name };
print "The name of a user with id $u->{id} is $u->{name}\n";
Note the *hash reference*.
my @u = db_fetch { return user->id, user->name };
for my $u (@u) {
print "$u->{id}:\t$u->{name}\n";
}
Note the *array of hash references*.
my @r = db_fetch {
my $u : users;
return $u->id, "$u->first_name $u->last_name";
}
What are the names of the columns?
my @r = db_fetch {
my $u : users;
return $u->id,
full_name => "$u->first_name $u->last_name";
}
db_update {
my $u : users;
$u->id == 42; # filter
$u->first_name = "Ford";
$u->last_name = "Prefect";
};
db_update {
my $u : users;
$u->id == 42; # filter
$u = {
first_name => "Ford",
last_name => "Prefect",
age => $u->age + 1,
};
};
db_delete {
users->id < 20;
};
db_insert 'users', {
id => 42,
first_name => "Ford",
last_name => "Prefect",
};
use DBI;
use DBIx::Perlish;
my $dbh = DBI->connect(...);
# this works just fine
my @rows = db_fetch { ... };
my @r = db_fetch {
users->name =~ /^ford/i;
};
my @r = db_fetch {
my $u : users;
$u->id == 1 ||
$u->id == 2 ||
$u->id == 3;
};
Boooooring
my @r = db_fetch {
users->id <- [1,2,3];
};
my @ids = (1,2,3);
my @r = db_fetch {
users->id <- @ids;
};
Also used for sub-queries.
db_delete {
my $u : users;
db_fetch {
$u->id == bad_users->users_id;
};
};
db_delete {
my $u : users;
$u->id <- db_fetch {
return bad_users->users_id;
};
};
This form must return a single value.
last;
... LIMIT 1;
last unless 5..20;
... OFFSET 5 LIMIT 16;
my $type = "ICBM";
db_fetch {
my $p : products;
$p->type eq $type if $type;
};
SELECT * FROM products where type = 'ICBM';
my $type = "";
db_fetch {
my $p : products;
$p->type eq $type if $type;
};
SELECT * FROM products;
db_fetch {
my $t : tab;
return $t->name, $t->type, count($t->age);
};
SELECT name, type, COUNT(age) FROM tab GROUP BY name, type
Aggregates: avg(), count(), max(), min()
db_fetch {
{
my $t1 : tab1;
$t1->id == 42;
} union {
my $t2 : tab2;
$t2->id == 666;
}
};
union, intersect, except
db_fetch {
my $x : x;
my $y : y;
join $y * $x <=
db_fetch { $y->id == $x->id }
};
Some functionality is implemented differently for different DBD drivers.
Regular expressions; pseudo-functions. More in the future (LIMIT/OFFSET, aggregates).
Thank you!
Any questions?