dialect/sql/sqlgraph: avoid creating tx blocks for single DELETE statements

In PostgreSQL, every statement is executed within a transaction. Therefore, we can avoid
creating transaction blocks manually (group of statements surrounded by BEGIN and COMMIT)
for DeleteNodes operation as it's implemented with a single statement.

Benchmark for 4000 operations was improved from:

	14.54s      7270455 ns/op    3702 B/op     81 allocs/op

To:

	5.36s      2679935 ns/op    2864 B/op     59 allocs/op

---

MySQL and SQLite share the same behavior. Please see https://github.com/ent/ent/pull/1858
for more info.
This commit is contained in:
Ariel Mashraki
2021-08-27 15:48:07 +03:00
committed by Ariel Mashraki
parent ee606f4e86
commit b23a0e8554
2 changed files with 4 additions and 12 deletions

View File

@@ -472,10 +472,6 @@ type DeleteSpec struct {
// DeleteNodes applies the DeleteSpec on the graph.
func DeleteNodes(ctx context.Context, drv dialect.Driver, spec *DeleteSpec) (int, error) {
tx, err := drv.Tx(ctx)
if err != nil {
return 0, err
}
var (
res sql.Result
builder = sql.Dialect(drv.Dialect())
@@ -487,14 +483,14 @@ func DeleteNodes(ctx context.Context, drv dialect.Driver, spec *DeleteSpec) (int
pred(selector)
}
query, args := builder.Delete(spec.Node.Table).Schema(spec.Node.Schema).FromSelect(selector).Query()
if err := tx.Exec(ctx, query, args, &res); err != nil {
return 0, rollback(tx, err)
if err := drv.Exec(ctx, query, args, &res); err != nil {
return 0, err
}
affected, err := res.RowsAffected()
if err != nil {
return 0, rollback(tx, err)
return 0, err
}
return int(affected), tx.Commit()
return int(affected), nil
}
// QuerySpec holds the information for querying

View File

@@ -1816,10 +1816,8 @@ func TestUpdateNodes(t *testing.T) {
func TestDeleteNodes(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
mock.ExpectBegin()
mock.ExpectExec(escape("DELETE FROM `users`")).
WillReturnResult(sqlmock.NewResult(0, 2))
mock.ExpectCommit()
affected, err := DeleteNodes(context.Background(), sql.OpenDB("", db), &DeleteSpec{
Node: &NodeSpec{
Table: "users",
@@ -1833,10 +1831,8 @@ func TestDeleteNodes(t *testing.T) {
func TestDeleteNodesSchema(t *testing.T) {
db, mock, err := sqlmock.New()
require.NoError(t, err)
mock.ExpectBegin()
mock.ExpectExec(escape("DELETE FROM `mydb`.`users`")).
WillReturnResult(sqlmock.NewResult(0, 2))
mock.ExpectCommit()
affected, err := DeleteNodes(context.Background(), sql.OpenDB("", db), &DeleteSpec{
Node: &NodeSpec{
Table: "users",