Show HN: fluent SQL – a minimalistic SQL builder for Java
github.com
github.com
Instead of:
new SQL().SELECT_ALL()
You could have Query.SELECT_ALL()Ideally Java would be cool with having Static and non-Static methods with identical signatures and names, but alas, looks like a static class Query or whatever would be the way to do this.
import static com.example.Query.*;
I wonder if the author was aware of the existence of jOOQ?
Most decent IDE's (Idea and few others) are clever enough to understand the SQL between quotation marks and if connected to database will give you instant errors if something is incorrect - misspelled names, missing commas, etc. Sometimes this can be a big time saver.
Just wondering.. did you create this to be used in the read layer of a DDD/CQS based system?
Edit: actually looking at the source it appears this one is similar to the one i saw in C# where each call just returns the same builder rather than a new version
Please don't take this as a dig at you or your code - everyone has an itch to scratch, and I'm quite sure writing this was fun.
Having typesafety transcend from the database to your "main" language is of advantage so long as you are using a statically typed language anyway.
All this is possible while maintaining much of the expressive power of SQL.
Essentially, I'm deeply uneasy about embedding translators from one language into another. As an example, not many people like using BigDecimal to describe arithmetic operations, despite it having a fluent syntax and improved type safety (e.g. around implicit conversions) compared to just writing an expression.
That's not what query builders (/expression languages) do. They just express the SQL in the host language to allow for compositions and the like.
Because like it or not, expressing SQL as a string is a pain in the ass to compose, you can't easily build a query incrementally.
With a query builder, you can. You're still writing SQL, it's not an object layer/ORM and it has (should have) a fairly direct mapping to SQL. You're just writing SQL in a way which fits better in the host languages.
Oh, it can also provide some measure of database-independence by having database-specific backend take care to handle specific incompatibilities between databases.
For instance for string concatenation[0] the standard is `||` which works in SQLite, Postgres and Oracle, MSSQL uses `+` instead of `||` and in MySQL `||` is the boolean OR unless you've activated a specific sql mode so you've got no choice but to use CONCAT (you could accept a performance hit and use CONCAT everywhere, except Oracle only supports an arity of 2 and SQLite doesn't support this function at all).
That's the kind of stuff a builder can handle for you under the hood, providing much improved cross-platform compatibility.
jOOQ is the first and only API to fully embed the SQL language as an internal domain-specific language in Java, using an internal BNF for API definition: http://blog.jooq.org/2012/01/19/jooqs-fluent-api-in-bnf-nota...
Being a DSL with an AST, advanced SQL transformation can be implemented to standardise SQL where common SQL constructs aren't supported. These include:
- DISTINCT predicate: http://blog.jooq.org/2012/09/21/the-is-distinct-from-predica...
- Row value expression predicates: http://blog.jooq.org/2013/05/03/sql-query-transformation-fun...
- Derived column lists: http://blog.jooq.org/2013/01/07/simulating-the-sql-standard
Both vendor-specific SQL and embedded SQL have their merits.
I guess it's a matter of taste, but it will certainly resolve ambiguities around Java's reserved words "case", "else", and "for".
A future version of jOOQ will ship with an API generator that can generate one or the other version of the DSL. Given that jOOQ is based on a somewhat formal BNF, such an evolution won't be too hard to implement.