Hi,

I was thinking how to abuse the p6 grammar to simplify the interface to SQL DBs.

- First i wanted to have a SELECT which works like a map.

- Then i wanted to use a pointy block to bind fields to variables.

- And i wanted also to make it lazy.


I come up to the following code:

    my $db = FakeDBI.new;
    my ($state, $dept) = <active storage>;

    my @out := $db.SELECT:
                    -> $username, $age, $salary {
                            say "fetched '$username'";
                            "$username => $salary, $age";
}, 'from users where state = ? and dept = ?', ($state, $dept);

    say "2nd: ", @out[1];
    say "1st: ", @out[0];
    say "4th: ", @out[3];


the fake module which make the above code to work (but do not really connect to a db):

    class FakeDBI {

            method SELECT(&block, $stm, *...@binds) {
                    my $sig = &block.signature;
                    my @fields = map {
$_.name ~~ /\$(\w+)/ or die "invalid signature params: "~$_.perl;
                            $/[0];
                    }, $sig.params;

                    my @stm = ("SELECT");
                    if @fields ~~ ('_') { push @stm, '*'; }
                    else { push @stm, join ', ', @fields; }
                    push @stm, $stm;

                    say 'DBG> prepare "', join ' ', @stm, '"';

                    gather {
                            say 'DBG> fake execute, fetching rows...';
                            for <john paul sara> -> $row {
my @data = map { $row ~ "_$_" }, @fields;
                                    take &block.(|@data);
                            }
                            say 'DBG> no more rows...';
                    }
            }
    }

and the output:

DBG> prepare "SELECT username, age, salary from users where state = ? and dept = ? "
    DBG> fake execute, fetching rows...
    fetched 'john_username'
    fetched 'paul_username'
    2nd: paul_username => paul_salary, paul_age
    1st: john_username => john_salary, john_age
    fetched 'sara_username'
    DBG> no more rows...
    4th: Any()


I found the usage very nice, and the lazyness may be removed by assigning instead of binding,
so i thought i should share this little useless example, HTH!

TODO: i would like to find a way to use the Signature for table names (select a.foo, b.bar),
but i don't want to make it too complex, any suggestion?


Oha

Reply via email to