[Dbix-class] Explicit ASTs (ping nate)

David E. Wheeler david at kineticode.com
Sun Sep 3 02:31:28 CEST 2006


On Sep 2, 2006, at 13:53, Matt S Trout wrote:

>    DWIM AST -> explicit AST -> SQL

Agreed. This way, the AST does not have to be specific to any one  
back end (PostgreSQL, SQLite, MySQL, LDAP, a object iterator, etc.).

This is also what I was thinking, as I've been trying to work out a  
DWIM query mini language that's just Perl and lexes itself into an  
AST that can then be passed to some other module to actually do  
something with.

> I reckon the basic query structure can be a hashref since we have
> @lots_of_clauses (and since we're bound to miss something first  
> time round)
> but each clause should probably be in arrayref form, so we have  
> something like
>
>    foo = 'yay' AND bar LIKE 'wooho%'

I'll just assume that you're using explicit SQL here, since we're not  
discussing the DWIM part. IOW, You're saying, to get the above, one  
has to create an AST like the below, yes?

> becoming
>
>    [ -op, 'AND',
>      [ -op, '=', [ -name, 'foo' ], [ -bind, 'yay' ] ],
>      [ -op, 'LIKE', [ -name, 'bar' ], [ -bind, 'wooho%' ] ],
>    ],
>
> and a function call like
>
>    COUNT( * )
>
> would become
>
>    [ -func, 'COUNT', '*' ]

Sure, that works for me.

> the basic principle here is that an op generally takes a specific  
> number of
> arguments, whereas a function is a containing clause that can take a
> potentially arbitrary number. So a complete statement might be  
> something like
>
>    SELECT my.a, my.b FROM my_table my WHERE spork = 1
>
> and that would become
>
>    {
>      select => [ [ -name, 'my', 'a' ], [ -name, 'my', 'b' ] ],

The '-name' key might be unnecessary, no? Unless there's something  
else that might be included? Oh, wait, there is. It should probably  
be something like:

   [ [ -name => 'my', -alias => 'a' ],
     [ -name => 'my', -alias => 'b' ],
   ]

If we're going to be precise (and pedantic). No? And since there  
multiple keys per token, it should actually probably be:

   [ { -name => 'my', -alias => 'a' },
     { -name => 'my', -alias => 'b' },
   ]

>      from => [ [ -alias, 'my_table', 'my' ] ],

That would have to be:

       from => [ { -name => 'my_table', -alias => 'my' } ]

>      where => [ [ -op, '=', [ -name, 'spork' ], [ -bind, 1 ] ] ],

And here:

      where => [ [ -op, '=', { -name => 'spork', -bind => 1 } ] ],

No?

>    }
>
> which is ... spectacularly ugly, but I -think- explicit enough. Fun  
> will be
> handling specific things like

Yes, I was making it even more explicit. Whether that's over the top  
or not I'm not sure. Also, I'm thinking that the -bind value ought to  
support a code ref, so that it could potentially bind a different  
value every time it's called.

>    MATCH (title,body) AGAINST ('database')
>
> but I guess that's just
>
>    [ -func, 'MATCH',
>      [ [ -name, 'title' ], [ -name, 'body' ] ],
>      [ [ -bind, 'database' ] ]
>    ]

Right.

> and have something like "func_specific_$func" and "func_generic"  
> methods on
> the emitter, so MATCH gets handled by func_specific_MATCH whereas  
> something
> "normal" like COUNT can go through func_generic (we'd enumerate the  
> specific
> methods at instantiation time for performance, I think).

Well, I think that COUNT() is only in the select or group by clauses,  
never in where. But I'd also like to explicitly include support for  
MATCH(), so that one can use regular expressions in WHERE clauses,  
just as one can use LIKE.

Best,

David





More information about the Dbix-class mailing list