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.

Reply via email to