Invalid JDBC Parameter or Column Index
ID |
kotlin.preparedstatement_resultset_methods_called_valid |
Severity |
critical |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Kotlin |
Tags |
reliability |
Description
Reports a PreparedStatement setter (setString, setInt, setDate, …) or a ResultSet
getter (getString, getInt, getDate, …) called with a statically resolvable index below 1.
The receiver’s resolved type has to be java.sql.PreparedStatement or java.sql.ResultSet, so
zero-based APIs that share a method name — MutableList.set(index, value), or
Statement.setFetchSize(rows), which configures the statement rather than binding a parameter — are not flagged. A receiver Kotlin’s type resolver cannot type, such as an untyped lambda
parameter of a use { } block, is left alone rather than guessed at.
Rationale
Both PreparedStatement parameters and ResultSet columns are numbered starting at 1, not 0.
Calling one of these methods with index 0 or a negative value always throws SQLException at
runtime, regardless of how many parameters or columns the statement actually has:
val insert: PreparedStatement = connection.prepareStatement("INSERT INTO users (name) VALUES (?)")
insert.setString(0, name) // always throws SQLException
val rows: ResultSet = insert.executeQuery()
rows.getString(0) // always throws SQLException
The mistake is easy to make in Kotlin because every other indexed API the language offers — lists, arrays, strings — is zero-based, so 0 is the reflex for "the first one".
Remediation
Start indexing parameters and columns at 1:
val insert: PreparedStatement = connection.prepareStatement("INSERT INTO users (name) VALUES (?)")
insert.setString(1, name)
val rows: ResultSet = insert.executeQuery()
rows.getString(1)
An index that is not a compile-time constant is never reported, so a loop that binds a variable
number of parameters is unaffected. Where the column layout is worth naming, read columns by
label (rows.getString("name")) instead of by position.