I'm working on a DSL for generating SQL queries, based loosely on
Python's SQLAlchemy and Ruby's Sequel. One nice thing about the
DSL is the compact syntax for specifying WHERE clauses. With some
fiddling, I got it working for opEquals, a simplified example:
foreach(network; db["networks"].each) {
writefln("network: %s", network.name);
foreach(host; db["hosts"].where(db.c.id == network.id)) {
writefln("\thost: %s", host.address);
}
}
This works because db.c.id returns a struct which defines an
opEquals which returns a "Filter" struct, rather than an int. I'm
not positive that it should really be allowed by the compiler,
but it works:
struct Filter { ... }
struct Column {
Filter opEquals(T)(T rhs) { ... }
}
Then the .where call takes a filter, and uses it to output a
snippet of sql like "id = 5"
However, this won't work for comparison operators like < and >,
which all map to opCmp, or for != (since that's rewritten to !(a
== b))
I guess I have two questions, one, am I going to shoot myself in
the foot by going down this path, because it only happens to work
due to the compiler being too lax? And is there interest in
extending D to allow the rest of the operators to return
non-boolean results? I'm thinking something like falling back to
opBinary!("<"), etc, if opCmp isn't defined for a struct.