sqladapter.Register   F
last analyzed

Complexity

Conditions 19

Size

Total Lines 81
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 62
nop 3
dl 0
loc 81
rs 0.5999
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like sqladapter.Register often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package sqladapter
2
3
import (
4
	"context"
5
	"database/sql"
6
	"database/sql/driver"
7
	"strings"
8
	"time"
9
10
	"github.com/cdleo/go-commons/logger"
11
	proxy "github.com/cdleo/go-sql-proxy"
12
)
13
14
func Register(connector SQLEngineConnector, translator SQLSyntaxTranslator, logger logger.Logger) {
15
16
	if isAlreadyRegistered(connector.DriverName()) {
17
		return
18
	}
19
20
	sql.Register(connector.DriverName(), proxy.NewProxyContext(connector.Driver(), &proxy.HooksContext{
21
		PostOpen: func(_ context.Context, _ interface{}, conn *proxy.Conn, err error) error {
22
			if err != nil {
23
				stdErr := connector.ErrorHandler(err)
24
				logger.Errorf(stdErr, "Open (source: %s)", err.Error())
25
				return stdErr
26
			}
27
			logger.Qry("Open")
28
			return nil
29
		},
30
		PostBegin: func(_ context.Context, _ interface{}, conn *proxy.Conn, err error) error {
31
			if err != nil {
32
				stdErr := connector.ErrorHandler(err)
33
				logger.Errorf(stdErr, "Begin (source: %s)", err.Error())
34
				return stdErr
35
			}
36
			logger.Qry("Begin")
37
			return nil
38
		},
39
		PostCommit: func(_ context.Context, _ interface{}, tx *proxy.Tx, err error) error {
40
			if err != nil {
41
				stdErr := connector.ErrorHandler(err)
42
				logger.Errorf(stdErr, "Commit (source: %s)", err.Error())
43
				return stdErr
44
			}
45
			logger.Qry("Commit")
46
			return nil
47
		},
48
		PostRollback: func(_ context.Context, _ interface{}, tx *proxy.Tx, err error) error {
49
			if err != nil {
50
				stdErr := connector.ErrorHandler(err)
51
				logger.Errorf(stdErr, "Rollback (source: %s)", err.Error())
52
				return stdErr
53
			}
54
			logger.Qry("Rollback")
55
			return nil
56
		},
57
		PrePrepare: func(_ context.Context, stmt *proxy.Stmt) (interface{}, error) {
58
			stmt.QueryString = translator.Translate(stmt.QueryString)
59
			return nil, nil
60
		},
61
		PostPrepare: func(_ context.Context, ctx interface{}, stmt *proxy.Stmt, err error) error {
62
			if err != nil {
63
				stdErr := connector.ErrorHandler(err)
64
				logger.Errorf(stdErr, "Prepare (source: %s)", err.Error())
65
				return stdErr
66
			}
67
			logger.Tracef("Prepare: %s", prettyQuery(stmt.QueryString))
68
			return nil
69
		},
70
		PreQuery: func(_ context.Context, stmt *proxy.Stmt, args []driver.NamedValue) (interface{}, error) {
71
			stmt.QueryString = translator.Translate(stmt.QueryString)
72
			return time.Now(), nil
73
		},
74
		PostQuery: func(_ context.Context, ctx interface{}, stmt *proxy.Stmt, args []driver.NamedValue, rows driver.Rows, err error) error {
75
			if err != nil {
76
				stdErr := connector.ErrorHandler(err)
77
				logger.Errorf(stdErr, "Query: %s; Args = %v (source: %s)", prettyQuery(stmt.QueryString), args, err.Error())
78
				return stdErr
79
			}
80
			logger.Tracef("Query: %s; Args = %v (%s)", prettyQuery(stmt.QueryString), args, time.Since(ctx.(time.Time)))
81
			return nil
82
		},
83
		PreExec: func(_ context.Context, stmt *proxy.Stmt, _ []driver.NamedValue) (interface{}, error) {
84
			stmt.QueryString = translator.Translate(stmt.QueryString)
85
			return time.Now(), nil
86
		},
87
		PostExec: func(_ context.Context, ctx interface{}, stmt *proxy.Stmt, args []driver.NamedValue, _ driver.Result, err error) error {
88
			if err != nil {
89
				stdErr := connector.ErrorHandler(err)
90
				logger.Errorf(stdErr, "Exec: %s; Args = %v (source: %s)", prettyQuery(stmt.QueryString), args, err.Error())
91
				return stdErr
92
			}
93
			logger.Tracef("Exec: %s; Args = %v (%s)", prettyQuery(stmt.QueryString), args, time.Since(ctx.(time.Time)))
94
			return nil
95
		},
96
	}))
97
}
98
99
func prettyQuery(query string) string {
100
	return strings.ReplaceAll(strings.ReplaceAll(query, "\t", ""), "\n", "")
101
}
102
103
func isAlreadyRegistered(proxyName string) bool {
104
105
	drivers := sql.Drivers()
106
	for _, item := range drivers {
107
		if item == proxyName {
108
			return true
109
		}
110
	}
111
112
	return false
113
}
114