github.com/gogf/gf/v2@v2.7.4/database/gdb/gdb_core_ctx.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gdb 8 9 import ( 10 "context" 11 "sync" 12 13 "github.com/gogf/gf/v2/errors/gcode" 14 "github.com/gogf/gf/v2/errors/gerror" 15 "github.com/gogf/gf/v2/os/gctx" 16 ) 17 18 // internalCtxData stores data in ctx for internal usage purpose. 19 type internalCtxData struct { 20 sync.Mutex 21 // Used configuration node in current operation. 22 ConfigNode *ConfigNode 23 } 24 25 // column stores column data in ctx for internal usage purpose. 26 type internalColumnData struct { 27 // The first column in result response from database server. 28 // This attribute is used for Value/Count selection statement purpose, 29 // which is to avoid HOOK handler that might modify the result columns 30 // that can confuse the Value/Count selection statement logic. 31 FirstResultColumn string 32 } 33 34 const ( 35 internalCtxDataKeyInCtx gctx.StrKey = "InternalCtxData" 36 internalColumnDataKeyInCtx gctx.StrKey = "InternalColumnData" 37 38 // `ignoreResultKeyInCtx` is a mark for some db drivers that do not support `RowsAffected` function, 39 // for example: `clickhouse`. The `clickhouse` does not support fetching insert/update results, 40 // but returns errors when execute `RowsAffected`. It here ignores the calling of `RowsAffected` 41 // to avoid triggering errors, rather than ignoring errors after they are triggered. 42 ignoreResultKeyInCtx gctx.StrKey = "IgnoreResult" 43 ) 44 45 func (c *Core) injectInternalCtxData(ctx context.Context) context.Context { 46 // If the internal data is already injected, it does nothing. 47 if ctx.Value(internalCtxDataKeyInCtx) != nil { 48 return ctx 49 } 50 return context.WithValue(ctx, internalCtxDataKeyInCtx, &internalCtxData{ 51 ConfigNode: c.config, 52 }) 53 } 54 55 func (c *Core) setConfigNodeToCtx(ctx context.Context, node *ConfigNode) error { 56 value := ctx.Value(internalCtxDataKeyInCtx) 57 if value == nil { 58 return gerror.NewCode(gcode.CodeInternalError, `no internal data found in context`) 59 } 60 61 data := value.(*internalCtxData) 62 data.Lock() 63 defer data.Unlock() 64 data.ConfigNode = node 65 return nil 66 } 67 68 func (c *Core) getConfigNodeFromCtx(ctx context.Context) *ConfigNode { 69 if value := ctx.Value(internalCtxDataKeyInCtx); value != nil { 70 data := value.(*internalCtxData) 71 data.Lock() 72 defer data.Unlock() 73 return data.ConfigNode 74 } 75 return nil 76 } 77 78 func (c *Core) injectInternalColumn(ctx context.Context) context.Context { 79 return context.WithValue(ctx, internalColumnDataKeyInCtx, &internalColumnData{}) 80 } 81 82 func (c *Core) getInternalColumnFromCtx(ctx context.Context) *internalColumnData { 83 if v := ctx.Value(internalColumnDataKeyInCtx); v != nil { 84 return v.(*internalColumnData) 85 } 86 return nil 87 } 88 89 func (c *Core) InjectIgnoreResult(ctx context.Context) context.Context { 90 if ctx.Value(ignoreResultKeyInCtx) != nil { 91 return ctx 92 } 93 return context.WithValue(ctx, ignoreResultKeyInCtx, true) 94 } 95 96 func (c *Core) GetIgnoreResultFromCtx(ctx context.Context) bool { 97 return ctx.Value(ignoreResultKeyInCtx) != nil 98 }