-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeleter.go
112 lines (101 loc) · 2.99 KB
/
deleter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package dalgo2sql
import (
"context"
"database/sql"
"fmt"
"github.com/dal-go/dalgo/dal"
"strings"
)
type statementExecutor = func(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
func (dtb *database) Delete(ctx context.Context, key *dal.Key) error {
return deleteSingle(ctx, dtb.options, key, dtb.db.ExecContext)
}
func (t transaction) Delete(ctx context.Context, key *dal.Key) error {
return deleteSingle(ctx, t.sqlOptions, key, t.tx.ExecContext)
}
func (dtb *database) DeleteMulti(ctx context.Context, keys []*dal.Key) error {
return deleteMulti(ctx, dtb.options, keys, dtb.db.ExecContext)
}
func deleteSingle(ctx context.Context, options Options, key *dal.Key, exec statementExecutor) error {
collection := key.Collection()
//goland:noinspection SqlNoDataSourceInspection
query := fmt.Sprintf("DELETE FROM %v WHERE ", key.Collection())
if rs, hasOptions := options.Recordsets[collection]; hasOptions && len(rs.PrimaryKey()) == 1 {
query += rs.PrimaryKey()[0].Name() + " = ?"
} else {
query += "ID = ?"
}
_, err := exec(ctx, query, key.ID)
if err != nil {
return err
}
return nil
}
func deleteMulti(ctx context.Context, options Options, keys []*dal.Key, exec statementExecutor) error {
var prevTable string
var tableKeys []*dal.Key
deleteByKeys := func(table string, keys []*dal.Key) error {
if len(keys) == 0 {
return nil
}
if len(keys) == 1 {
if err := deleteSingle(ctx, options, keys[0], exec); err != nil {
return err
}
return nil
}
for _, key := range keys {
if err := deleteSingle(ctx, options, key, exec); err != nil {
return err
}
}
if err := deleteMultiInSingleTable(ctx, options, keys, exec); err != nil {
return err
}
return nil // TODO: code above commented out as tests are failing for RAMSQL driver.
}
for i, key := range keys {
kind := key.Collection()
if kind == prevTable {
tableKeys = append(tableKeys, key)
continue
}
if prevTable != "" {
if err := deleteByKeys(prevTable, tableKeys); err != nil {
return err
}
}
prevTable = kind
tableKeys = make([]*dal.Key, 1, len(keys)-i)
tableKeys[0] = key
}
if len(tableKeys) > 0 {
if err := deleteByKeys(prevTable, tableKeys); err != nil {
return err
}
}
return nil
}
func deleteMultiInSingleTable(ctx context.Context, options Options, keys []*dal.Key, exec statementExecutor) error {
pkCol := "ID"
collection := keys[0].Collection()
if rs, hasOptions := options.Recordsets[collection]; hasOptions && len(rs.primaryKey) == 1 {
pkCol = rs.primaryKey[0].Name()
}
query := fmt.Sprintf("DELETE FROM %v WHERE %v IN (", collection, pkCol)
args := make([]interface{}, len(keys))
q := make([]string, len(keys))
for i, key := range keys {
args[i] = key.ID
q[i] = "?"
}
query += strings.Join(q, ", ") + ")"
_, err := exec(ctx, query, args...)
if err != nil {
return err
}
return nil
}
func (t transaction) DeleteMulti(ctx context.Context, keys []*dal.Key) error {
return deleteMulti(ctx, t.sqlOptions, keys, t.tx.ExecContext)
}