Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[BUG] Ktorm no longer supports Postgresql DO NOTHING #248

@FeatureSpitter

Description

@FeatureSpitter

Hello @vincentlauvlwj

I remember we implemented this feature in this PR.

In the feature of this commit, it was possible to do something like:

      database.bulkInsert(Employees) {
          item {
              set(it.id, 1)
              set(it.name, "vince")
              set(it.job, "engineer")
              set(it.salary, 1000)
              set(it.hireDate, LocalDate.now())
              set(it.departmentId, 1)
          }
          item {
              set(it.id, 5)
              set(it.name, "vince")
              set(it.job, "engineer")
              set(it.salary, 1000)
              set(it.hireDate, LocalDate.now())
              set(it.departmentId, 1)
          }

          onDuplicateKey(Employees.id) {
              // I am leaving this intentionally empty, so Postgresql will ignore this error and proceed inserting the others
             // INSERT INTO ... ON CONFLICT (employee_id) DO NOTHING
          }
      }

This behavior was tested in ktorm-support-postgresql/src/test/kotlin/org/ktorm/support/postgresql/PostgreSqlTest.kt function testBulkInsertWithUpdate. And implemented here.

This is the visitor function as you have it now:

   protected open fun visitInsertOrUpdate(expr: InsertOrUpdateExpression): InsertOrUpdateExpression {
        writeKeyword("insert into ")
        visitTable(expr.table)
        writeInsertColumnNames(expr.assignments.map { it.column })
        writeKeyword("values ")
        writeInsertValues(expr.assignments)

        if (expr.updateAssignments.isNotEmpty()) {
            writeKeyword("on conflict ")
            writeInsertColumnNames(expr.conflictColumns)
            writeKeyword("do update set ")
            visitColumnAssignments(expr.updateAssignments)
        }

        return expr
    }

This is how it should be in order to support the DO NOTHING feature that Postgresql provides, as we did in that PR:

    protected open fun visitInsertOrUpdate(expr: InsertOrUpdateExpression): InsertOrUpdateExpression {
        writeKeyword("insert into ")
        visitTable(expr.table)
        writeInsertColumnNames(expr.assignments.map { it.column })
        writeKeyword("values ")
        writeInsertValues(expr.assignments)

        if (expr.conflictColumns.isNotEmpty()) {
            writeKeyword("on conflict ")
            writeInsertColumnNames(expr.conflictColumns)
            
            if (expr.updateAssignments.isNotEmpty()) {
                writeKeyword("do update set ")
                visitColumnAssignments(expr.updateAssignments)
            } else {
                writeKeyword("do nothing ")
            }
        }

        return expr
    }

Also, not forgetting now about the returning feature as well, so the final function for 3.4.0 would actually be:

    protected open fun visitInsertOrUpdate(expr: InsertOrUpdateExpression): InsertOrUpdateExpression {
        writeKeyword("insert into ")
        visitTable(expr.table)
        writeInsertColumnNames(expr.assignments.map { it.column })
        writeKeyword("values ")
        writeInsertValues(expr.assignments)

        if (expr.conflictColumns.isNotEmpty()) {
            writeKeyword("on conflict ")
            writeInsertColumnNames(expr.conflictColumns)

            if (expr.updateAssignments.isNotEmpty()) {
                writeKeyword("do update set ")
                visitColumnAssignments(expr.updateAssignments)
            } else {
                writeKeyword("do nothing ")
            }
        }

        if (expr.returningColumns.isNotEmpty()) {
            writeKeyword(" returning ")
            expr.returningColumns.forEachIndexed { i, column ->
                if (i > 0) write(", ")
                checkColumnName(column.name)
                write(column.name.quoted)
            }
        }

        return expr
    }

Please can you fix this here and on the other Postgresql dialect functions where the DO NOTHING feature got removed?
I think it is only the visitBulkInsert function that needs this fix as well. Also the test that tested this feature (linked above) should be recovered as well.

PS. It doesn't seem like it, but this is an important feature which I see no reason to forbid Ktorm users from using it. As it is now, the user is always forced to unnecessarily update one column in order to get conflict errors ignored. This is not ideal in terms of performance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions