{"record":{"id":"7e668ee26b1809c1","repo":"prestodb/presto","slug":"this-method-cannot-be-called-on-preparedstatement","errorCode":null,"errorMessage":"This method cannot be called on PreparedStatement","messagePattern":"This method cannot be called on PreparedStatement","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoPreparedStatement.java","lineNumber":701,"sourceCode":"    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream)\n            throws SQLException\n    {\n        throw new SQLFeatureNotSupportedException(\"setBlob\");\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader reader)\n            throws SQLException\n    {\n        throw new SQLFeatureNotSupportedException(\"setNClob\");\n    }\n\n    @Override\n    public ResultSet executeQuery(String sql)\n            throws SQLException\n    {\n        throw new SQLException(\"This method cannot be called on PreparedStatement\");\n    }\n\n    @Override\n    public int executeUpdate(String sql)\n            throws SQLException\n    {\n        throw new SQLException(\"This method cannot be called on PreparedStatement\");\n    }\n\n    @Override\n    public int executeUpdate(String sql, int autoGeneratedKeys)\n            throws SQLException\n    {\n        throw new SQLException(\"This method cannot be called on PreparedStatement\");\n    }\n\n    @Override\n    public int executeUpdate(String sql, int[] columnIndexes)","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoPreparedStatement.java#L683-L719","documentation":"PrestoPreparedStatement implements java.sql.PreparedStatement, whose contract forbids executing raw SQL text through the Statement-inherited methods. Calling executeQuery(String) on a PreparedStatement would bypass parameter binding, so the driver unconditionally throws SQLException with this message. The SQL must instead be supplied at prepareStatement() time and executed via the no-argument executeQuery().","triggerScenarios":"Calling prestoPreparedStatement.executeQuery(\"SELECT ...\") with a SQL string on an object obtained from connection.prepareStatement(sql). The throw is unconditional — there is no state in which this method succeeds.","commonSituations":"Refactored code that switched from createStatement() to prepareStatement() but kept the old executeQuery(sql) call; generic query-runner utilities that accept a Statement and a SQL string and dispatch to executeQuery(sql); ORMs or connection pools sharing a code path between Statement and PreparedStatement.","solutions":["Move the SQL into connection.prepareStatement(sql) and call ps.executeQuery() with no arguments","If the SQL is not parameterized, obtain a Statement via connection.createStatement() and keep executeQuery(sql)","Fix generic helper methods to detect PreparedStatement (instanceof) and use the no-arg execute path","Update the failing call site so it never passes a SQL string to a PreparedStatement"],"exampleFix":"// before\nPreparedStatement ps = conn.prepareStatement(\"SELECT * FROM t WHERE id = ?\");\nps.setLong(1, id);\nResultSet rs = ps.executeQuery(\"SELECT * FROM t WHERE id = ?\");\n// after\nPreparedStatement ps = conn.prepareStatement(\"SELECT * FROM t WHERE id = ?\");\nps.setLong(1, id);\nResultSet rs = ps.executeQuery();","handlingStrategy":"validation","validationCode":"if (stmt instanceof java.sql.PreparedStatement) {\n    ((java.sql.PreparedStatement) stmt).executeQuery();\n} else {\n    stmt.executeQuery(sql);\n}","typeGuard":"boolean isPreparedStatement(java.sql.Statement s) { return s instanceof java.sql.PreparedStatement; }","tryCatchPattern":"try {\n    rs = ps.executeQuery();\n} catch (SQLException e) {\n    if (e.getMessage().contains(\"cannot be called on PreparedStatement\")) {\n        throw new IllegalStateException(\"SQL text must be passed to prepareStatement(), not executeQuery(String)\", e);\n    }\n    throw e;\n}","preventionTips":["Always pass SQL only to connection.prepareStatement(sql)","Never call execute*/executeUpdate*/executeQuery overloads that take a String on a PreparedStatement","In generic JDBC utilities, branch on instanceof PreparedStatement before executing","Add static analysis or code-review checks banning String-taking execute methods on PreparedStatement variables"],"tags":["jdbc","presto","api-misuse"],"backgroundTag":"method-not-supported-on-prepared-statement","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}