Skip to content

DeleteAll uses wrong order of args and deletes wrong entries #1430

Closed
@eklatzer

Description

@eklatzer

Hey, with version v4.17.0 a performance improvement for the DeleteAll func was introduced:

Fix performance issue with DeleteAll by using a WHERE IN instead of WHERE OR (thanks @jakeiotechsys)
PR: https://github.com/volatiletech/sqlboiler/pull/1376/files

This seems to break existing usages of DeleteAll on tables with multiple primary key columns.
Example:

CREATE TABLE articles (
    primary_key_1 int NOT NULL,
    primary_key_2 int NOT NULL,
    title text NOT NULL,
    PRIMARY KEY (primary_key_1, primary_key_2)
);

Generates the following model:

sql := "DELETE FROM \"articles\" WHERE " +
		strmangle.WhereInClause(string(dialect.LQ), string(dialect.RQ), 1, articlePrimaryKeyColumns, len(o))

Example usage:

f.Article1 = &models.Article{
  PrimaryKey1: 100,
  PrimaryKey2: 200,
  Title:       "Article 1",
}

f.Article2 = &models.Article{
  PrimaryKey1: 300,
  PrimaryKey2: 400,
  Title:       "Article 2",
}

f.Article3 = &models.Article{
  PrimaryKey1: 500,
  PrimaryKey2: 600,
  Title:       "Article 3",
}

ctx := context.Background()

articleSlice := models.ArticleSlice{
	fixtures.Article1,
	fixtures.Article2,
	fixtures.Article3,
}

_, err := articleSlice.DeleteAll(boil.WithDebug(ctx, true), s.DB)
require.NoError(t, err)

DELETE FROM "articles" WHERE "primary_key_1" IN ($1,$2,$3) AND "primary_key_2" IN ($4,$5,$6)
[100 200 300 400 500 600]

-> DELETE FROM "articles" WHERE "primary_key_1" IN (100,200,300) AND "primary_key_2" IN (400,500,600)

This leads to the following two bugs:

  • The wrong args are used for the wrong field (100, 200, 300 as primary_key_1, even though primary_key_1 is 100, 300, 500)
  • Even if the args were used correct, the query would still delete items, that should not be deleted:
DELETE FROM "articles" WHERE "primary_key_1" IN (100, 300, 500) AND "primary_key_2" IN (200, 400, 600)

This would e.g. also delete the entry with primary_key_1=100 and primary_key_2=600 even though only 100/200 was requested

With WhereClauseRepeated the SQL was:

DELETE FROM "articles" WHERE ("primary_key_1"=$1 AND "primary_key_2"=$2) OR ("primary_key_1"=$3 AND "primary_key_2"=$4) OR ("primary_key_1"=$5 AND "primary_key_2"=$6)
[100 200 300 400 500 600]

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions