impossibl / pgjdbc-ng

A new JDBC driver for PostgreSQL aimed at supporting the advanced features of JDBC and Postgres
https://impossibl.github.io/pgjdbc-ng
Other
602 stars 108 forks source link

IndexOutOfBoundsException: Index: 0, Size: 0 #545

Open JajaComp opened 3 years ago

JajaComp commented 3 years ago

Hi! I use exposed kotlin version 0.31.1 com.impossibl.pgjdbc-ng:pgjdbc-ng:0.8.9 After code:

fun insertOperation(
        operationId: UUID,
        deviceId: UUID,
        history: List<HistoryInput>
    ): Unit = transaction {
        HistoryEntity.batchInsert(historyOperationStages, ignore = true) {
            this[HistoryEntity.id] = it.history_id
            this[HistoryEntity.operation_id] = operationId
            this[HistoryEntity.stage_id] = it.stage_id
            this[HistoryEntity.author_id] = it.author_id
            this[HistoryEntity.date_time] = it.date_time
            this[HistoryEntity.device_id] = deviceId
        }
    }

exposed function arguments:

fun <T : Table, E> T.batchInsert(
    data: Iterable<E>,
    ignore: Boolean = false,
    shouldReturnGeneratedValues: Boolean = true,
    body: BatchInsertStatement.(E) -> Unit
): List<ResultRow>

i got error:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:659)
    at java.util.ArrayList.remove(ArrayList.java:498)
    at com.impossibl.postgres.protocol.RowDataSet.take(RowDataSet.java:78)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.finishRequest(PGPreparedStatement.java:540)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.finishRequests(PGPreparedStatement.java:566)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.executeBatch(PGPreparedStatement.java:499)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.executeBatch(PGPreparedStatement.java:417)
    at org.jetbrains.exposed.sql.statements.jdbc.JdbcPreparedStatementImpl.executeBatch(JdbcPreparedStatementImpl.kt:48)
    at org.jetbrains.exposed.sql.statements.InsertStatement.execInsertFunction(InsertStatement.kt:111)
    at org.jetbrains.exposed.sql.statements.InsertStatement.executeInternal(InsertStatement.kt:117)
    at org.jetbrains.exposed.sql.statements.InsertStatement.executeInternal(InsertStatement.kt:11)
    at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:60)
    at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:129)
    at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:115)
    at org.jetbrains.exposed.sql.statements.Statement.execute(Statement.kt:28)
    at org.jetbrains.exposed.sql.QueriesKt.batchInsert(Queries.kt:134)
    at org.jetbrains.exposed.sql.QueriesKt.batchInsert$default(Queries.kt:89)

I think problem do add exist item and after ignore returning empty result

kdubb commented 3 years ago

@JajaComp Can you make a simple reproducing project?

Hc747 commented 1 year ago

Hi @kdubb, sorry for the grave dig. Have encountered and replicated this issue myself.

CREATE TABLE my_table(a INTEGER NOT NULL PRIMARY KEY, b INTEGER);
Connection connection = ...;
PreparedStatement statement = connection.prepareStatement("INSERT INTO my_table (a, b) VALUES (?, ?) ON CONFLICT (a) DO NOTHING RETURNING (a);", RETURN_GENERATED_KEYS);

statement.setInt(1, 1);
statement.setInt(2, 1);
statement.addBatch();

statement.setInt(1, 1);
statement.setInt(2, 2);
statement.addBatch();

statement.executeBatch(); // Line 540 of PGPreparedStatement: 

Happy path (insert one):

image

Unhappy path (insert two):

image

Results in:

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
    at java.base/java.util.Objects.checkIndex(Objects.java:359)
    at java.base/java.util.ArrayList.remove(ArrayList.java:504)
    at com.impossibl.postgres.protocol.RowDataSet.take(RowDataSet.java:78)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.finishRequest(PGPreparedStatement.java:540)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.finishRequests(PGPreparedStatement.java:566)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.executeBatch(PGPreparedStatement.java:499)
    at com.impossibl.postgres.jdbc.PGPreparedStatement.executeBatch(PGPreparedStatement.java:417)