-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
gdb_core_ctx.go
98 lines (83 loc) · 3.05 KB
/
gdb_core_ctx.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
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gdb
import (
"context"
"sync"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gctx"
)
// internalCtxData stores data in ctx for internal usage purpose.
type internalCtxData struct {
sync.Mutex
// Used configuration node in current operation.
ConfigNode *ConfigNode
}
// column stores column data in ctx for internal usage purpose.
type internalColumnData struct {
// The first column in result response from database server.
// This attribute is used for Value/Count selection statement purpose,
// which is to avoid HOOK handler that might modify the result columns
// that can confuse the Value/Count selection statement logic.
FirstResultColumn string
}
const (
internalCtxDataKeyInCtx gctx.StrKey = "InternalCtxData"
internalColumnDataKeyInCtx gctx.StrKey = "InternalColumnData"
// `ignoreResultKeyInCtx` is a mark for some db drivers that do not support `RowsAffected` function,
// for example: `clickhouse`. The `clickhouse` does not support fetching insert/update results,
// but returns errors when execute `RowsAffected`. It here ignores the calling of `RowsAffected`
// to avoid triggering errors, rather than ignoring errors after they are triggered.
ignoreResultKeyInCtx gctx.StrKey = "IgnoreResult"
)
func (c *Core) injectInternalCtxData(ctx context.Context) context.Context {
// If the internal data is already injected, it does nothing.
if ctx.Value(internalCtxDataKeyInCtx) != nil {
return ctx
}
return context.WithValue(ctx, internalCtxDataKeyInCtx, &internalCtxData{
ConfigNode: c.config,
})
}
func (c *Core) setConfigNodeToCtx(ctx context.Context, node *ConfigNode) error {
value := ctx.Value(internalCtxDataKeyInCtx)
if value == nil {
return gerror.NewCode(gcode.CodeInternalError, `no internal data found in context`)
}
data := value.(*internalCtxData)
data.Lock()
defer data.Unlock()
data.ConfigNode = node
return nil
}
func (c *Core) getConfigNodeFromCtx(ctx context.Context) *ConfigNode {
if value := ctx.Value(internalCtxDataKeyInCtx); value != nil {
data := value.(*internalCtxData)
data.Lock()
defer data.Unlock()
return data.ConfigNode
}
return nil
}
func (c *Core) injectInternalColumn(ctx context.Context) context.Context {
return context.WithValue(ctx, internalColumnDataKeyInCtx, &internalColumnData{})
}
func (c *Core) getInternalColumnFromCtx(ctx context.Context) *internalColumnData {
if v := ctx.Value(internalColumnDataKeyInCtx); v != nil {
return v.(*internalColumnData)
}
return nil
}
func (c *Core) InjectIgnoreResult(ctx context.Context) context.Context {
if ctx.Value(ignoreResultKeyInCtx) != nil {
return ctx
}
return context.WithValue(ctx, ignoreResultKeyInCtx, true)
}
func (c *Core) GetIgnoreResultFromCtx(ctx context.Context) bool {
return ctx.Value(ignoreResultKeyInCtx) != nil
}