Should we actually make Connection a TemplateProcessor?

Ethan McCue ethan at mccue.dev
Fri Sep 15 14:31:17 UTC 2023


One of the examples in the String Template JEPs, and a stated motivating
factor behind its design, is SQL. Template processors are objects so that
use cases like constructing SQL statements aren't injection prone.

The questions I want to pose are:

* Should java.sql provide an implementation of TemplateProcessor
* Where should that implementation live?
* What, exactly, should be the translation strategy.

The reason I think this isn't an obvious yes and ask that last question is
this.

Say this is some user's code.

try (var conn = ds.getConnection();
     var stmt = conn.prepareStatement("""
         SELECT user.name
         WHERE user.height > ? AND user.width < ?
         """)) {
    stmt.setInt(1, height);
    stmt.setInt(2, width);
    var rs = stmt.executeQuery();
    process(rs);
}

The transliteration to string templates would be something like

try (var conn = ds.getConnection();
     var stmt = conn."""
         SELECT user.name
         WHERE user.height > \{height} AND user.width < \{width}
         """)) {
    var rs = stmt.executeQuery();
    process(rs);
}

Whether Connection implements TemplateProcessor directly or its something
that you wrap a connection with is somewhat immaterial.

How should we handle "partial templating"?

try (var conn = ds.getConnection();
     var stmt = conn."""
         SELECT user.name
         WHERE user.height > ? AND user.width < \{width}
         """)) {
    var rs = stmt.executeQuery();
    rs.setInt(1, height);
    process(rs);
}

Or

try (var conn = ds.getConnection();
     var stmt = conn."""
         SELECT user.name
         WHERE user.height > \{height} AND user.width < ?
         """)) {
    var rs = stmt.executeQuery();
    rs.setInt(2, width);
    process(rs);
}

Is replacing every substitution with ? and calling set* is enough? How
could it be known, without parsing the specific sql dialect, what index to
use for the parameter?

try (var conn = ds.getConnection();
     var stmt = conn."""
         SELECT user.name
         WHERE user.name <> '???'
             AND user.height > ?
             AND user.width < \{width}
         """)) {
    var rs = stmt.executeQuery();
    rs.setInt(1, height);
    process(rs);
}

(this seems more library design than language design, hence I sent it here.
I can forward to amber-dev if that is better)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20230915/074d2d51/attachment.htm>


More information about the core-libs-dev mailing list