Closed
Description
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 thoughprimary_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]