tursodatabase/turso · error · SQLException
turso does not support stored procedures
Error message
turso does not support stored procedures
What it means
prepareCall (all overloads) throws because CallableStatement, the JDBC interface for stored procedures, is unsupported: a SQLite-compatible engine has no stored procedures to call. The exception is thrown for any SQL string passed, including plain SELECTs, since CallableStatement itself is not implemented by this driver.
Source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java:225
public CallableStatement prepareCall(String sql) throws SQLException {
return prepareCall(
sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return prepareCall(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
@Override
public CallableStatement prepareCall(
String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
throw new SQLException("turso does not support stored procedures");
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return prepareStatement(
sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
}
@Override
public PreparedStatement prepareStatement(
String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {View on GitHub (pinned to bad083fafb)
Solutions
- Replace CallableStatement with PreparedStatement executing the equivalent inline SQL (SELECT for queries, INSERT/UPDATE/DELETE for mutations).
- Move stored-procedure logic into application code (a service method wrapping plain statements in one transaction).
- For small pieces of server-side logic, consider SQL triggers or views where they genuinely substitute.
- Remove @NamedStoredProcedureQuery / statementType="CALLABLE" mappings when migrating to Turso.
Example fix
// before
try (CallableStatement cs = conn.prepareCall("{call get_customer(?)}")) {
cs.setLong(1, customerId);
ResultSet rs = cs.executeQuery();
}
// after
try (PreparedStatement ps = conn.prepareStatement(
"SELECT id, name FROM customers WHERE id = ?")) {
ps.setLong(1, customerId);
ResultSet rs = ps.executeQuery();
} Defensive patterns
Strategy: validation
Validate before calling
private static boolean isStoredProcedureCall(String sql) {
String s = sql.trim().toLowerCase(Locale.ROOT);
return s.startsWith("{call") || s.startsWith("{") || s.contains("call ");
}
if (isStoredProcedureCall(sql)) {
throw new UnsupportedOperationException(
"stored procedures are not supported by Turso; inline the SQL instead");
} Type guard
private static boolean requiresCallableStatement(String sql) {
return isStoredProcedureCall(sql);
} Try / catch
try {
stmt = conn.prepareCall(sql);
} catch (SQLException e) {
if (sql.trim().startsWith("{")) {
throw new UnsupportedOperationException(
"rewrite stored procedure call as inline SQL: " + sql, e);
}
throw e;
} Prevention
- Ban CallableStatement in codebases targeting SQLite-compatible engines (enforce with ArchUnit or lint rules).
- Inline stored-procedure bodies as SQL statements coordinated in a service method.
- Remove @NamedStoredProcedureQuery and statementType="CALLABLE" mappings during migration.
- Add a migration checklist item: search for '{call' and prepareCall.
When it happens
Trigger: conn.prepareCall("{call some_proc(?)}"); JPA/Hibernate StoredProcedureQuery usage; MyBatis mappers with CallableStatement statementType; iBATIS/legacy DAO code; any {call ...} escape-syntax SQL.
Common situations: Porting an application from Oracle/SQL Server/PostgreSQL that uses stored procedures; JPA repositories declaring @NamedStoredProcedureQuery; reporting tools that fetch data via procedures; generated data-access code that defaults to prepareCall for all reads.
Related errors
- turso only supports CLOSE_CURSORS_AT_COMMIT
- Savepoints are not supported by Turso
- createClob not supported
- createBlob not supported
- createNClob not supported
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/d62fe7b8ce4e058f.
Report an issue: GitHub.