If you work with Java/JDBC long enough, you eventually run into this situation:
You have code like this:
String sql = "SELECT * FROM users WHERE id = ? AND status = ?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setLong(1, userId);
pst.setString(2, status);
And then, from a log or debugger, you know something like:
userId = 42
status = ACTIVE
But what you actually need is the SQL you can paste into your database client:
SELECT * FROM users
WHERE id = 42
AND status = 'ACTIVE';
Doing this once is trivial.
Doing it repeatedly while debugging production issues is annoying.
It gets worse when:
- the SQL is split across several Java strings;
- values come from map.get("KEY");
- there are dates or timestamps;
- strings contain apostrophes;
- some parameters are unresolved;
- the method contains several PreparedStatements.
I kept doing this manually, so I built a small tool called Bind2SQL.
What it does
Bind2SQL takes Java/JDBC code and reconstructs the executable SQL.
For example:
String sql = "SELECT * FROM person "
+ "WHERE person_id = ? "
+ "AND type_id = ? "
+ "AND created_at >= ?";
PreparedStatement pst = con.prepareStatement(sql);
pst.setLong(1, values.get("PERSON_ID"));
pst.setInt(2, values.get("TYPE_ID"));
pst.setDate(3, Date.valueOf("2026-09-02"));
With runtime values:
{PERSON_ID=12648350, TYPE_ID=29}
It produces something like:
SELECT *
FROM person
WHERE person_id = 12648350
AND type_id = 29
AND created_at >= DATE '2026-09-02';
The important part is that unresolved parameters are not silently guessed.
If Bind2SQL cannot resolve something, it leaves it clearly marked so you can review it manually.
Why I made it browser-only
I often use this kind of tool with real application code and runtime values.
That may include:
- internal SQL;
- identifiers;
- production log values;
- table names;
- application-specific data.
So I didn't want a server in the middle.
Bind2SQL runs entirely in the browser.
There is:
- no backend;
- no account;
- no upload;
- no database;
- no external processing.
The Java code and values you paste stay on your machine.
Current scope
The free version currently focuses on reconstructing one PreparedStatement at a time.
It supports common JDBC setters such as:
setString
setInt
setLong
setShort
setByte
setBoolean
setBigDecimal
setDouble
setFloat
setDate
setTimestamp
setTime
setNull
It can also resolve common expressions such as:
values.get("USER_ID")
from pasted runtime values like:
{USER_ID=42, STATUS=ACTIVE}
It is intentionally a pragmatic parser, not a complete Java compiler.
Very dynamic SQL may still require manual review.
Try it
The free version is available here:
No signup required.
I would like real JDBC examples
What I'm most interested in now is not adding random features.
I want to find real Java/JDBC patterns that break the parser.
If you work with PreparedStatement, I'd be interested in examples involving things like:
- unusual setter patterns;
- SQL assembled across multiple variables;
- maps or DTOs;
- nullable parameters;
- timestamps;
- reused statement variables;
- legacy JDBC code.
If you find something Bind2SQL doesn't handle correctly, open an issue or leave an example in the comments.
That feedback is much more useful to me right now than adding features based on guesses.
Top comments (0)