reposilite-playground / exposed-upsert

Upsert DSL extension for Exposed, Kotlin SQL framework
The Unlicense
34 stars 3 forks source link

SqlLite: Invalid sql leads to ArrayIndexOutOfBoundsException #1

Closed NichtStudioCode closed 3 years ago

NichtStudioCode commented 3 years ago

Stacktrace: https://pastebin.com/raw/XzKVWhuB

This is my upsert statement:

TileEntitiesTable.upsert(
    conflictColumn = TileEntitiesTable.uuid,

    insertBody = {
        val location = tileEntity.location

        it[uuid] = tileEntity.uuid
        it[world] = tileEntity.location.world!!.uid
        it[chunkX] = chunk.x
        it[chunkZ] = chunk.z
        it[x] = location.blockX
        it[y] = location.blockY
        it[z] = location.blockZ
        it[yaw] = tileEntity.armorStand.location.yaw
        it[type] = tileEntity.material.typeName
        it[data] = ExposedBlob(tileEntity.getData())
    },

    updateBody = {
        it[data] = ExposedBlob(tileEntity.getData())
    }
)

The above upsert statement generates this sql:

INSERT INTO tileEntities (chunkX, chunkZ, "data", "type", uuid, world, x, y, yaw, z) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT("uuid") DO UPDATE SET "data"=EXCLUDED."data"

As you can see, the statement is invalid, there should be another question mark in the update statement after "data"= This leads to an ArrayIndexOutOfBoundsException in CorePreparedStatement.java.

I fixed it in this commit: https://github.com/NichtStudioCode/exposed-upsert/commit/297be27e8ab2aad81c404676653f2d0320650271. This is obviously not a perfect solution, hence why I am not making a pull request.

dzikoysk commented 3 years ago

Well, in general this library is not a perfect solution and in a perfect world it wouldn't even exist 😅

updateBody was designed to work with with(SqlExpressionBuilder) { (expressions), I don't have even a test for such a raw call. I'll see if I can do something more about it, the ${transaction.identity(column)}=EXCLUDED.${transaction.identity(column)} was proposed by community in Exposed Upsert thread and I didn't really changed this call.

dzikoysk commented 3 years ago

I didn't find better solution, Exposed query builder engine randomly reinterprets arguments (and I don't know how can I control this behaviour), so it's better to use ? and make a note, that we have to updates fields from both, insert and update, bodies in the same order.