alexfu / SQLiteQueryBuilder

A library that provides a simple API for building SQLite query statements in Java.
MIT License
70 stars 21 forks source link

Improve statement string builder #2

Closed alexfu closed 9 years ago

alexfu commented 9 years ago

Currently statements are built by using a series of append operations on StringBuilder. This is not exactly ideal since it is very vulnerable to bugs and mistakes. Look into a better, safer method.

shadeven commented 9 years ago

@alexfu, StringBuilder is not too bad, except it's not thread-safe. Do you have anything in mind?

alexfu commented 9 years ago

I've been spending some time thinking about this and i've come up with the following...

Instead of appending to a single centralized StringBuilder in the constructor, we store the needed arguments into local variables and then compose it together with a call to either toString or build.

The below example features a SelectBuilder and a SelectFromBuilder. Both implement SegmentBuilder which is just an interface with a build method.

public class SelectBuilder implements SegmentBuilder {
  private final String[] fields;

  public SelectBuilder(String...fields) {
    this.fields = fields;
  }

  public SelectFromBuilder from(String table) {
    return new SelectFromBuilder(this, table);
  }

  @Override
  public String build() {
    return join(" ", "SELECT", join(",", fields));
  }
}
public class SelectFromBuilder implements SegmentBuilder {
  private SelectBuilder prefix;
  private String[] tables;

  public SelectFromBuilder(SelectBuilder prefix, String...tables) {
    this.prefix = prefix;
    this.tables = tables;
  }

  @Override
  public String build() {
    return join(" ", prefix.build(), "FROM", join(",", tables));
  }
}

The join method is simply a helper method to concatenate strings together on a delimiter. The order in which the statement is built will occur in reverse order. So instead of creating the statement starting from "SELECT", it will start at the end and should append it's parent (i.e. prefix) to itself as shown in the build function of SelectFromBuilder.

We would use the following like so...

public class SQLiteQueryBuilder {
  public static SelectBuilder select(String... fields) {
    return new SelectBuilder(fields);
  }
}

If you can't find any possible issues with this, I'll start working on it.

shadeven commented 9 years ago

@alexfu, the new approach discards inheritance and uses composition instead, which is a better design. Apart from that, honestly I don't see much benefit from this. Please elaborate more if possible.

If you insist to go ahead, then I will wait for your commits as my code will depend on it. Cheers, Steven