Re: Should we actually make Connection a TemplateProcessor?

2023-09-15 Thread Jim Laskey
I’ve been tinkering with just such an implementation. Here are a few issues 
that I’m sussing out:

- compound templates (partial templates)
- identifier vs string
- lists of identifiers, strings and values
  - list separators (comma, or, and)
- lack of meta data for some platforms
- odd ball data types (blobs)

There are others but these are the ones I’m starting with. There are lots of 
options to play with; format specification, DSL, new data types.

I’ll be looking for input from the experts leading to a JEP at some point, but 
haven’t worked out the forum as yet. Stay tuned.

Cheers,

— Jim






On Sep 15, 2023, at 11:31 AM, Ethan McCue  wrote:

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.


Should we actually make Connection a TemplateProcessor?

2023-09-15 Thread Ethan McCue
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)