Skip to content

Commit 3e8f974

Browse files
authored
refine cache plan (#14)
1 parent bcd9fbc commit 3e8f974

File tree

7 files changed

+125
-62
lines changed

7 files changed

+125
-62
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,15 @@ type Format = {
4949

5050
type Query = SelectQuery | UpdateQuery | DeleteQuery | InsertQuery
5151

52+
type Placeholder = {
53+
index: number;
54+
extra?: boolean
55+
}
56+
5257
type Condition = {
5358
column: string
54-
value?: number | string
59+
operator: 'eq' | 'in'
60+
placeholder: Placeholder
5561
}
5662

5763
type SelectQuery = CachableSelectQuery | NonCachableSelectQuery
@@ -62,8 +68,6 @@ type CachableSelectQuery = {
6268
cache: true
6369
table: string
6470
targets: string[]
65-
// ?の位置と一致するような順番
66-
// 固定値でWHEREしている場合は最後に
6771
conditions: Condition[]
6872
orders: {
6973
column: string

domains/cache_plan.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,24 @@ const (
2626
CachePlanQueryType_INSERT CachePlanQueryType = "insert"
2727
)
2828

29+
type CachePlanPlaceholder struct {
30+
Index int `yaml:"index"`
31+
Extra bool `yaml:"extra,omitempty"`
32+
}
33+
2934
type CachePlanCondition struct {
30-
Column string `yaml:"column"`
31-
Value interface{} `yaml:"value,omitempty"`
35+
Column string `yaml:"column"`
36+
Operator CachePlanOperatorEnum `yaml:"operator,omitempty"`
37+
Placeholder CachePlanPlaceholder `yaml:"placeholder"`
3238
}
3339

40+
type CachePlanOperatorEnum string
41+
42+
const (
43+
CachePlanOperator_EQ CachePlanOperatorEnum = "eq"
44+
CachePlanOperator_IN CachePlanOperatorEnum = "in"
45+
)
46+
3447
type CachePlanOrder struct {
3548
Column string `yaml:"column"`
3649
Order CachePlanOrderEnum `yaml:"order"`
@@ -51,10 +64,15 @@ type CachePlanSelectQuery struct {
5164
Orders []CachePlanOrder `yaml:"orders,omitempty"`
5265
}
5366

67+
type CachePlanUpdateTarget struct {
68+
Column string `yaml:"column"`
69+
Placeholder CachePlanPlaceholder `yaml:"placeholder"`
70+
}
71+
5472
type CachePlanUpdateQuery struct {
55-
Table string `yaml:"table"`
56-
Targets []string `yaml:"targets"`
57-
Conditions []CachePlanCondition `yaml:"conditions,omitempty"`
73+
Table string `yaml:"table"`
74+
Targets []CachePlanUpdateTarget `yaml:"targets"`
75+
Conditions []CachePlanCondition `yaml:"conditions,omitempty"`
5876
}
5977

6078
type CachePlanDeleteQuery struct {

domains/cache_plan_repository_test.go

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ var formatted = `queries:
2121
- created_at
2222
conditions:
2323
- column: livestream_id
24+
operator: eq
25+
placeholder:
26+
index: 0
2427
orders:
2528
- column: created_at
2629
order: desc
@@ -35,26 +38,46 @@ var formatted = `queries:
3538
- COUNT()
3639
conditions:
3740
- column: livestream_id
41+
operator: eq
42+
placeholder:
43+
index: 0
3844
- query: DELETE FROM livecomments WHERE id = ? AND livestream_id = ? AND (SELECT COUNT(*) FROM (SELECT ? AS text) AS texts INNER JOIN (SELECT CONCAT('%', ?, '%') AS pattern) AS patterns ON texts.text LIKE patterns.pattern) >= 1;
3945
type: delete
4046
table: livecomments
4147
conditions:
4248
- column: id
49+
operator: eq
50+
placeholder:
51+
index: 0
4352
- column: livestream_id
53+
operator: eq
54+
placeholder:
55+
index: 1
4456
- query: DELETE FROM livestream_viewers_history WHERE user_id = ? AND livestream_id = ?
4557
type: delete
4658
table: livestream_viewers_history
4759
conditions:
4860
- column: user_id
61+
operator: eq
62+
placeholder:
63+
index: 0
4964
- column: livestream_id
50-
- query: UPDATE settings SET value = ? WHERE name = 'payment_gateway_url'
65+
operator: eq
66+
placeholder:
67+
index: 1
68+
- query: UPDATE settings SET value = ? WHERE name = ?
5169
type: update
5270
table: settings
5371
targets:
54-
- value
72+
- column: value
73+
placeholder:
74+
index: 0
5575
conditions:
5676
- column: name
57-
value: payment_gateway_url
77+
operator: eq
78+
placeholder:
79+
index: 0
80+
extra: true
5881
`
5982

6083
var parsed = &CachePlan{
@@ -65,11 +88,15 @@ var parsed = &CachePlan{
6588
Query: "SELECT * FROM livecomments WHERE livestream_id = ? ORDER BY created_at DESC",
6689
},
6790
Select: &CachePlanSelectQuery{
68-
Table: "livecomments",
69-
Cache: true,
70-
Targets: []string{"id", "user_id", "livestream_id", "comment", "tip", "created_at"},
71-
Conditions: []CachePlanCondition{{Column: "livestream_id"}},
72-
Orders: []CachePlanOrder{{Column: "created_at", Order: "desc"}},
91+
Table: "livecomments",
92+
Cache: true,
93+
Targets: []string{"id", "user_id", "livestream_id", "comment", "tip", "created_at"},
94+
Conditions: []CachePlanCondition{
95+
{Column: "livestream_id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 0}},
96+
},
97+
Orders: []CachePlanOrder{
98+
{Column: "created_at", Order: "desc"},
99+
},
73100
},
74101
},
75102
{
@@ -87,10 +114,12 @@ var parsed = &CachePlan{
87114
Type: CachePlanQueryType_SELECT,
88115
},
89116
Select: &CachePlanSelectQuery{
90-
Table: "livestream_viewers_history",
91-
Cache: true,
92-
Targets: []string{"COUNT()"},
93-
Conditions: []CachePlanCondition{{Column: "livestream_id"}},
117+
Table: "livestream_viewers_history",
118+
Cache: true,
119+
Targets: []string{"COUNT()"},
120+
Conditions: []CachePlanCondition{
121+
{Column: "livestream_id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 0}},
122+
},
94123
},
95124
},
96125
{
@@ -99,8 +128,11 @@ var parsed = &CachePlan{
99128
Type: CachePlanQueryType_DELETE,
100129
},
101130
Delete: &CachePlanDeleteQuery{
102-
Table: "livecomments",
103-
Conditions: []CachePlanCondition{{Column: "id"}, {Column: "livestream_id"}},
131+
Table: "livecomments",
132+
Conditions: []CachePlanCondition{
133+
{Column: "id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 0}},
134+
{Column: "livestream_id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 1}},
135+
},
104136
},
105137
},
106138
{
@@ -109,19 +141,26 @@ var parsed = &CachePlan{
109141
Type: CachePlanQueryType_DELETE,
110142
},
111143
Delete: &CachePlanDeleteQuery{
112-
Table: "livestream_viewers_history",
113-
Conditions: []CachePlanCondition{{Column: "user_id"}, {Column: "livestream_id"}},
144+
Table: "livestream_viewers_history",
145+
Conditions: []CachePlanCondition{
146+
{Column: "user_id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 0}},
147+
{Column: "livestream_id", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 1}},
148+
},
114149
},
115150
},
116151
{
117152
CachePlanQueryBase: &CachePlanQueryBase{
118-
Query: "UPDATE settings SET value = ? WHERE name = 'payment_gateway_url'",
153+
Query: "UPDATE settings SET value = ? WHERE name = ?",
119154
Type: CachePlanQueryType_UPDATE,
120155
},
121156
Update: &CachePlanUpdateQuery{
122-
Table: "settings",
123-
Targets: []string{"value"},
124-
Conditions: []CachePlanCondition{{Column: "name", Value: "payment_gateway_url"}},
157+
Table: "settings",
158+
Targets: []CachePlanUpdateTarget{
159+
{Column: "value", Placeholder: CachePlanPlaceholder{Index: 0}},
160+
},
161+
Conditions: []CachePlanCondition{
162+
{Column: "name", Operator: CachePlanOperator_EQ, Placeholder: CachePlanPlaceholder{Index: 0, Extra: true}},
163+
},
125164
},
126165
},
127166
},

normalizer/normalizer.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import (
66
"regexp"
77
"strconv"
88
"strings"
9-
10-
"github.com/traP-jp/h24w-17/domains"
119
)
1210

11+
type ExtraArg struct {
12+
Column string
13+
Value interface{}
14+
}
15+
1316
type NormalizedQuery struct {
14-
Query string
15-
ExtraConditions []domains.CachePlanCondition
17+
Query string
18+
ExtraArgs []ExtraArg
1619
}
1720

1821
func unwrapInt(s string) int {
@@ -27,45 +30,45 @@ var patterns = []replacementPattern{
2730
{
2831
regex: regexp.MustCompile(`(?i)\b([a-z]+)\s*=\s*(\d+)`),
2932
replacement: "$1 = ?",
30-
condition: func(match []string) *domains.CachePlanCondition {
31-
return &domains.CachePlanCondition{Column: match[1], Value: unwrapInt(match[2])}
33+
condition: func(match []string) *ExtraArg {
34+
return &ExtraArg{Column: match[1], Value: unwrapInt(match[2])}
3235
},
3336
},
3437
{
3538
regex: regexp.MustCompile(`(?i)\b([a-z]+)\s*=\s*['"]([^']*)['"]`),
3639
replacement: "$1 = ?",
37-
condition: func(match []string) *domains.CachePlanCondition {
38-
return &domains.CachePlanCondition{Column: match[1], Value: match[2]}
40+
condition: func(match []string) *ExtraArg {
41+
return &ExtraArg{Column: match[1], Value: match[2]}
3942
},
4043
},
4144
{
4245
regex: regexp.MustCompile(`(?i)\b(IN|VALUES)\s*\(\s*\?\s*(?:\s*,\s*\?)*\s*\)`),
4346
replacement: "$1 (?)",
44-
condition: func(match []string) *domains.CachePlanCondition {
47+
condition: func(match []string) *ExtraArg {
4548
return nil
4649
},
4750
},
4851
{
4952
regex: regexp.MustCompile(`(?i)\bLIMIT\s+(\d+)`),
5053
replacement: "LIMIT ?",
51-
condition: func(match []string) *domains.CachePlanCondition {
52-
return &domains.CachePlanCondition{Column: "LIMIT()", Value: unwrapInt(match[1])}
54+
condition: func(match []string) *ExtraArg {
55+
return &ExtraArg{Column: "LIMIT()", Value: unwrapInt(match[1])}
5356
},
5457
},
5558
}
5659

5760
type replacementPattern struct {
5861
regex *regexp.Regexp
5962
replacement string
60-
condition func(match []string) *domains.CachePlanCondition
63+
condition func(match []string) *ExtraArg
6164
}
6265

6366
func NormalizeQuery(query string) (NormalizedQuery, error) {
6467
if query == "" {
6568
return NormalizedQuery{}, errors.New("query cannot be empty")
6669
}
6770

68-
extraConditions := []domains.CachePlanCondition{}
71+
extraArgs := []ExtraArg{}
6972

7073
normalizedQuery := query
7174

@@ -77,7 +80,7 @@ func NormalizeQuery(query string) (NormalizedQuery, error) {
7780
if pattern.condition != nil {
7881
condition := pattern.condition(match)
7982
if condition != nil {
80-
extraConditions = append(extraConditions, *condition)
83+
extraArgs = append(extraArgs, *condition)
8184
}
8285
}
8386
}
@@ -87,7 +90,7 @@ func NormalizeQuery(query string) (NormalizedQuery, error) {
8790
normalizedQuery = strings.TrimSpace(normalizedQuery)
8891

8992
return NormalizedQuery{
90-
Query: normalizedQuery,
91-
ExtraConditions: extraConditions,
93+
Query: normalizedQuery,
94+
ExtraArgs: extraArgs,
9295
}, nil
9396
}

normalizer/normalizer_test.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/assert"
8-
"github.com/traP-jp/h24w-17/domains"
98
)
109

1110
func TestNormalizeQuery(t *testing.T) {
@@ -16,15 +15,15 @@ func TestNormalizeQuery(t *testing.T) {
1615
{
1716
query: "SELECT * FROM users WHERE id = ?;",
1817
expected: NormalizedQuery{
19-
Query: "SELECT * FROM users WHERE id = ?;",
20-
ExtraConditions: []domains.CachePlanCondition{},
18+
Query: "SELECT * FROM users WHERE id = ?;",
19+
ExtraArgs: []ExtraArg{},
2120
},
2221
},
2322
{
2423
query: "SELECT * FROM users WHERE id = 1;",
2524
expected: NormalizedQuery{
2625
Query: "SELECT * FROM users WHERE id = ?;",
27-
ExtraConditions: []domains.CachePlanCondition{
26+
ExtraArgs: []ExtraArg{
2827
{Column: "id", Value: 1},
2928
},
3029
},
@@ -33,7 +32,7 @@ func TestNormalizeQuery(t *testing.T) {
3332
query: "SELECT * FROM users WHERE id = 1 AND name = 'John';",
3433
expected: NormalizedQuery{
3534
Query: "SELECT * FROM users WHERE id = ? AND name = ?;",
36-
ExtraConditions: []domains.CachePlanCondition{
35+
ExtraArgs: []ExtraArg{
3736
{Column: "id", Value: 1},
3837
{Column: "name", Value: "John"},
3938
},
@@ -43,23 +42,23 @@ func TestNormalizeQuery(t *testing.T) {
4342
query: "SELECT * FROM users ORDER BY created_at LIMIT 1;",
4443
expected: NormalizedQuery{
4544
Query: "SELECT * FROM users ORDER BY created_at LIMIT ?;",
46-
ExtraConditions: []domains.CachePlanCondition{
45+
ExtraArgs: []ExtraArg{
4746
{Column: "LIMIT()", Value: 1},
4847
},
4948
},
5049
},
5150
{
5251
query: "SELECT * FROM users WHERE id IN (?, ?, ?);",
5352
expected: NormalizedQuery{
54-
Query: "SELECT * FROM users WHERE id IN (?);",
55-
ExtraConditions: []domains.CachePlanCondition{},
53+
Query: "SELECT * FROM users WHERE id IN (?);",
54+
ExtraArgs: []ExtraArg{},
5655
},
5756
},
5857
{
5958
query: "INSERT INTO users (id, name) VALUES (?, ?, ?, ?, ?, ?);",
6059
expected: NormalizedQuery{
61-
Query: "INSERT INTO users (id, name) VALUES (?);",
62-
ExtraConditions: []domains.CachePlanCondition{},
60+
Query: "INSERT INTO users (id, name) VALUES (?);",
61+
ExtraArgs: []ExtraArg{},
6362
},
6463
},
6564
}

template/driver.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ func (c *CacheConn) Prepare(rawQuery string) (driver.Stmt, error) {
9898
return nil, err
9999
}
100100
return &CustomCacheStatement{
101-
inner: innerStmt,
102-
rawQuery: rawQuery,
103-
query: normalized.Query,
104-
extraConditions: normalized.ExtraConditions,
105-
queryInfo: queryInfo,
101+
inner: innerStmt,
102+
rawQuery: rawQuery,
103+
query: normalized.Query,
104+
extraArgs: normalized.ExtraArgs,
105+
queryInfo: queryInfo,
106106
}, nil
107107
}
108108

0 commit comments

Comments
 (0)