Skip to content

Commit b767856

Browse files
- Initial commit
1 parent ca38e41 commit b767856

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed

code.go

Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
package code
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"errors"
7+
"fmt"
8+
"reflect"
9+
"strconv"
10+
"strings"
11+
)
12+
13+
const (
14+
DriverPostgres = "postgres"
15+
DriverMysql = "mysql"
16+
DriverMssql = "mssql"
17+
DriverOracle = "oracle"
18+
DriverNotSupport = "no support"
19+
)
20+
21+
type CodeModel struct {
22+
Id string `mapstructure:"id" json:"id,omitempty" gorm:"column:id" bson:"id,omitempty" dynamodbav:"id,omitempty" firestore:"id,omitempty"`
23+
Code string `mapstructure:"code" json:"code,omitempty" gorm:"column:code" bson:"code,omitempty" dynamodbav:"code,omitempty" firestore:"code,omitempty"`
24+
Value string `mapstructure:"value" json:"value,omitempty" gorm:"column:value" bson:"value,omitempty" dynamodbav:"value,omitempty" firestore:"value,omitempty"`
25+
Name string `mapstructure:"name" json:"name,omitempty" gorm:"column:name" bson:"name,omitempty" dynamodbav:"name,omitempty" firestore:"name,omitempty"`
26+
Text string `mapstructure:"text" json:"text,omitempty" gorm:"column:text" bson:"text,omitempty" dynamodbav:"text,omitempty" firestore:"text,omitempty"`
27+
Sequence int32 `mapstructure:"sequence" json:"sequence,omitempty" gorm:"column:sequence" bson:"sequence,omitempty" dynamodbav:"sequence,omitempty" firestore:"sequence,omitempty"`
28+
}
29+
type CodeConfig struct {
30+
Master string `mapstructure:"master" json:"master,omitempty" gorm:"column:master" bson:"master,omitempty" dynamodbav:"master,omitempty" firestore:"master,omitempty"`
31+
Id string `mapstructure:"id" json:"id,omitempty" gorm:"column:id" bson:"id,omitempty" dynamodbav:"id,omitempty" firestore:"id,omitempty"`
32+
Code string `mapstructure:"code" json:"code,omitempty" gorm:"column:code" bson:"code,omitempty" dynamodbav:"code,omitempty" firestore:"code,omitempty"`
33+
Text string `mapstructure:"text" json:"text,omitempty" gorm:"column:text" bson:"text,omitempty" dynamodbav:"text,omitempty" firestore:"text,omitempty"`
34+
Name string `mapstructure:"name" json:"name,omitempty" gorm:"column:name" bson:"name,omitempty" dynamodbav:"name,omitempty" firestore:"name,omitempty"`
35+
Value string `mapstructure:"value" json:"value,omitempty" gorm:"column:value" bson:"value,omitempty" dynamodbav:"value,omitempty" firestore:"value,omitempty"`
36+
Sequence string `mapstructure:"sequence" json:"sequence,omitempty" gorm:"column:sequence" bson:"sequence,omitempty" dynamodbav:"sequence,omitempty" firestore:"sequence,omitempty"`
37+
Status string `mapstructure:"status" json:"status,omitempty" gorm:"column:status" bson:"status,omitempty" dynamodbav:"status,omitempty" firestore:"status,omitempty"`
38+
Active interface{} `mapstructure:"active" json:"active,omitempty" gorm:"column:active" bson:"active,omitempty" dynamodbav:"active,omitempty" firestore:"active,omitempty"`
39+
}
40+
type CodeLoader interface {
41+
Load(ctx context.Context, master string) ([]CodeModel, error)
42+
}
43+
type SqlCodeLoader struct {
44+
DB *sql.DB
45+
Table string
46+
Config CodeConfig
47+
Driver string
48+
}
49+
type DynamicSqlCodeLoader struct {
50+
DB *sql.DB
51+
Query string
52+
ParameterCount int
53+
HandleDriver bool
54+
Driver string
55+
}
56+
func NewDefaultDynamicSqlCodeLoader(db *sql.DB, query string) *DynamicSqlCodeLoader {
57+
driver := GetDriver(db)
58+
return &DynamicSqlCodeLoader{DB: db, Query: query, ParameterCount: 0, HandleDriver: true, Driver: driver}
59+
}
60+
func NewDynamicSqlCodeLoader(db *sql.DB, query string, parameterCount int, handleDriver bool) *DynamicSqlCodeLoader {
61+
driver := GetDriver(db)
62+
return &DynamicSqlCodeLoader{DB: db, Query: query, ParameterCount: parameterCount, HandleDriver: handleDriver, Driver: driver}
63+
}
64+
func (l DynamicSqlCodeLoader) Load(ctx context.Context, master string) ([]CodeModel, error) {
65+
models := make([]CodeModel, 0)
66+
params := make([]interface{}, 0)
67+
params = append(params, master)
68+
if l.ParameterCount > 1 {
69+
for i := 2; i <= l.ParameterCount; i++ {
70+
params = append(params, master)
71+
}
72+
}
73+
driver := l.Driver
74+
if l.HandleDriver {
75+
if driver == DriverOracle || driver == DriverPostgres {
76+
var x string
77+
if driver == DriverOracle {
78+
x = ":val"
79+
} else {
80+
x = "$"
81+
}
82+
for i := 0; i < len(params); i++ {
83+
count := i + 1
84+
l.Query = strings.Replace(l.Query, "?", x + strconv.Itoa(count), 1)
85+
}
86+
}
87+
}
88+
rows, er1 := l.DB.Query(l.Query, params...)
89+
if er1 != nil {
90+
return models, er1
91+
}
92+
defer rows.Close()
93+
columns, er2 := rows.Columns()
94+
if er2 != nil {
95+
return models, er2
96+
}
97+
// get list indexes column
98+
modelTypes := reflect.TypeOf(models).Elem()
99+
modelType := reflect.TypeOf(CodeModel{})
100+
indexes, er3 := GetColumnIndexes(modelType, columns, driver)
101+
if er3 != nil {
102+
return models, er3
103+
}
104+
tb, er4 := ScanType(rows, modelTypes, indexes)
105+
if er4 != nil {
106+
return models, er4
107+
}
108+
for _, v := range tb {
109+
if c, ok := v.(*CodeModel); ok {
110+
models = append(models, *c)
111+
}
112+
}
113+
return models, nil
114+
}
115+
func NewSqlCodeLoader(db *sql.DB, table string, config CodeConfig) *SqlCodeLoader {
116+
driver := GetDriver(db)
117+
return &SqlCodeLoader{DB: db, Table: table, Config: config, Driver: driver}
118+
}
119+
func (l SqlCodeLoader) Load(ctx context.Context, master string) ([]CodeModel, error) {
120+
models := make([]CodeModel, 0)
121+
s := make([]string, 0)
122+
values := make([]interface{}, 0)
123+
sql2 := ""
124+
125+
c := l.Config
126+
if len(c.Id) > 0 {
127+
sf := fmt.Sprintf("%s as id", c.Id)
128+
s = append(s, sf)
129+
}
130+
if len(c.Code) > 0 {
131+
sf := fmt.Sprintf("%s as code", c.Code)
132+
s = append(s, sf)
133+
}
134+
if len(c.Name) > 0 {
135+
sf := fmt.Sprintf("%s as name", c.Name)
136+
s = append(s, sf)
137+
}
138+
if len(c.Value) > 0 {
139+
sf := fmt.Sprintf("%s as value", c.Value)
140+
s = append(s, sf)
141+
}
142+
if len(c.Text) > 0 {
143+
sf := fmt.Sprintf("%s as text", c.Text)
144+
s = append(s, sf)
145+
}
146+
osequence := ""
147+
if len(c.Sequence) > 0 {
148+
osequence = fmt.Sprintf("order by %s", c.Sequence)
149+
}
150+
p1 := ""
151+
i := 1
152+
if len(c.Master) > 0 {
153+
i = i + 1
154+
if l.Driver == DriverPostgres {
155+
p1 = fmt.Sprintf("%s = $1", c.Master)
156+
} else if l.Driver == DriverOracle {
157+
p1 = fmt.Sprintf("%s = :val1", c.Master)
158+
} else {
159+
p1 = fmt.Sprintf("%s = ?", c.Master)
160+
}
161+
values = append(values, master)
162+
}
163+
cols := strings.Join(s, ",")
164+
if len(c.Status) > 0 && c.Active != nil {
165+
p2 := ""
166+
if l.Driver == DriverPostgres {
167+
p2 = fmt.Sprintf("%s = $%d", c.Status, i)
168+
} else if l.Driver == DriverOracle {
169+
p1 = fmt.Sprintf("%s = :val%d", c.Status, i)
170+
}else {
171+
p2 = fmt.Sprintf("%s = ?", c.Status)
172+
}
173+
values = append(values, c.Active)
174+
if cols == "" {
175+
cols = "*"
176+
}
177+
if len(p1) > 0 {
178+
sql2 = fmt.Sprintf("select %s from %s where %s and %s %s", cols, l.Table, p1, p2, osequence)
179+
} else {
180+
sql2 = fmt.Sprintf("select %s from %s where %s %s", cols, l.Table, p2, osequence)
181+
}
182+
} else {
183+
if cols == "" {
184+
cols = "*"
185+
}
186+
if len(p1) > 0 {
187+
sql2 = fmt.Sprintf("select %s from %s where %s %s", cols, l.Table, p1, osequence)
188+
} else {
189+
sql2 = fmt.Sprintf("select %s from %s %s", cols, l.Table, osequence)
190+
}
191+
}
192+
if len(sql2) > 0 {
193+
if l.Driver == DriverOracle || l.Driver == DriverPostgres {
194+
var x string
195+
if l.Driver == DriverOracle {
196+
x = ":val"
197+
} else {
198+
x = "$"
199+
}
200+
for i := 0; i < len(values); i++ {
201+
count := i + 1
202+
sql2 = strings.Replace(sql2, "?", x+strconv.Itoa(count), 1)
203+
}
204+
}
205+
rows, err1 := l.DB.Query(sql2, values...)
206+
if err1 != nil {
207+
return nil, err1
208+
}
209+
defer rows.Close()
210+
columns, er1 := rows.Columns()
211+
if er1 != nil {
212+
return nil, er1
213+
}
214+
// get list indexes column
215+
modelTypes := reflect.TypeOf(models).Elem()
216+
modelType := reflect.TypeOf(CodeModel{})
217+
indexes, er2 := GetColumnIndexes(modelType, columns, GetDriver(l.DB))
218+
if er2 != nil {
219+
return nil, er2
220+
}
221+
tb, er3 := ScanType(rows, modelTypes, indexes)
222+
if er3 != nil {
223+
return nil, er3
224+
}
225+
for _, v := range tb {
226+
if c, ok := v.(*CodeModel); ok {
227+
models = append(models, *c)
228+
}
229+
}
230+
}
231+
return models, nil
232+
}
233+
234+
// StructScan : transfer struct to slice for scan
235+
func StructScan(s interface{}, indexColumns []int) (r []interface{}) {
236+
if s != nil {
237+
maps := reflect.Indirect(reflect.ValueOf(s))
238+
for _, index := range indexColumns {
239+
r = append(r, maps.Field(index).Addr().Interface())
240+
}
241+
}
242+
return
243+
}
244+
245+
func GetColumnIndexes(modelType reflect.Type, columnsName []string, driver string) (indexes []int, err error) {
246+
if modelType.Kind() != reflect.Struct {
247+
return nil, errors.New("bad type")
248+
}
249+
for i := 0; i < modelType.NumField(); i++ {
250+
field := modelType.Field(i)
251+
ormTag := field.Tag.Get("gorm")
252+
column, ok := FindTag(ormTag, "column")
253+
if driver == DriverOracle {
254+
column = strings.ToUpper(column)
255+
}
256+
if ok {
257+
if contains(columnsName, column) {
258+
indexes = append(indexes, i)
259+
}
260+
}
261+
}
262+
return
263+
}
264+
265+
func FindTag(tag string, key string) (string, bool) {
266+
if has := strings.Contains(tag, key); has {
267+
str1 := strings.Split(tag, ";")
268+
num := len(str1)
269+
for i := 0; i < num; i++ {
270+
str2 := strings.Split(str1[i], ":")
271+
for j := 0; j < len(str2); j++ {
272+
if str2[j] == key {
273+
return str2[j+1], true
274+
}
275+
}
276+
}
277+
}
278+
return "", false
279+
}
280+
281+
func contains(array []string, v string) bool {
282+
for _, s := range array {
283+
if s == v {
284+
return true
285+
}
286+
}
287+
return false
288+
}
289+
290+
func ScanType(rows *sql.Rows, modelTypes reflect.Type, indexes []int) (t []interface{}, err error) {
291+
for rows.Next() {
292+
initArray := reflect.New(modelTypes).Interface()
293+
if err = rows.Scan(StructScan(initArray, indexes)...); err == nil {
294+
t = append(t, initArray)
295+
}
296+
}
297+
return
298+
}
299+
300+
func GetDriver(db *sql.DB) string {
301+
driver := reflect.TypeOf(db.Driver()).String()
302+
switch driver {
303+
case "*pq.Driver":
304+
return DriverPostgres
305+
case "*mysql.MySQLDriver":
306+
return DriverMysql
307+
case "*mssql.Driver":
308+
return DriverMssql
309+
case "*godror.drv":
310+
return DriverOracle
311+
default:
312+
return DriverNotSupport
313+
}
314+
}

0 commit comments

Comments
 (0)