Skip to content

Commit 513cfbb

Browse files
committed
first commmit
1 parent b354cc0 commit 513cfbb

File tree

3 files changed

+406
-0
lines changed

3 files changed

+406
-0
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/feiin/sqlstring
2+
3+
go 1.16

sql.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package sqlstring
2+
3+
import (
4+
"encoding/hex"
5+
"encoding/json"
6+
"fmt"
7+
"reflect"
8+
"strconv"
9+
"strings"
10+
"time"
11+
)
12+
13+
var (
14+
tmFmtZero = "0000-00-00 00:00:00"
15+
tmFmtWithMS = "2006-01-02 15:04:05.999"
16+
escaper = "'"
17+
nullStr = "NULL"
18+
)
19+
20+
//Escape escape the val for sql
21+
func Escape(val interface{}) string {
22+
return EscapeInLocation(val, time.Local)
23+
}
24+
25+
func timeToString(t time.Time, loc *time.Location) string {
26+
if t.IsZero() {
27+
return escaper + tmFmtZero + escaper
28+
}
29+
30+
if loc != nil {
31+
return escaper + t.In(loc).Format(tmFmtWithMS) + escaper
32+
}
33+
return escaper + t.Format(tmFmtWithMS) + escaper
34+
}
35+
36+
func arrayToString(refValue reflect.Value, loc *time.Location) string {
37+
var res []string
38+
for i := 0; i < refValue.Len(); i++ {
39+
res = append(res, EscapeInLocation(refValue.Index(i).Interface(), loc))
40+
}
41+
return strings.Join(res, ",")
42+
}
43+
44+
func bytesToString(b []byte) string {
45+
return "X" + escaper + hex.EncodeToString(b) + escaper
46+
}
47+
48+
//EscapeInLocation escape the val with time.Location
49+
func EscapeInLocation(val interface{}, loc *time.Location) string {
50+
if val == nil {
51+
return nullStr
52+
}
53+
54+
switch v := val.(type) {
55+
case bool:
56+
return strconv.FormatBool(v)
57+
case time.Time:
58+
return timeToString(v, loc)
59+
case *time.Time:
60+
if v == nil {
61+
return nullStr
62+
}
63+
return timeToString(*v, loc)
64+
case []byte:
65+
return bytesToString(v)
66+
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
67+
return fmt.Sprintf("%d", v)
68+
case float32, float64:
69+
return fmt.Sprintf("%.6f", v)
70+
71+
case string:
72+
return escaper + strings.Replace(v, escaper, "\\"+escaper, -1) + escaper
73+
default:
74+
refValue := reflect.ValueOf(v)
75+
if v == nil || !refValue.IsValid() {
76+
return nullStr
77+
}
78+
79+
if refValue.IsNil() {
80+
return nullStr
81+
}
82+
83+
if refValue.Kind() == reflect.Ptr && !refValue.IsZero() {
84+
return EscapeInLocation(reflect.Indirect(refValue).Interface(), loc)
85+
}
86+
87+
if refValue.Kind() == reflect.Array || refValue.Kind() == reflect.Slice {
88+
//slice or array
89+
return arrayToString(refValue, loc)
90+
}
91+
92+
stringifyData, err := json.Marshal(v)
93+
if err != nil {
94+
return nullStr
95+
}
96+
return escaper + strings.Replace(string(stringifyData), escaper, "\\"+escaper, -1) + escaper
97+
98+
}
99+
}
100+
101+
//Format format the sql with args
102+
func Format(query string, args ...interface{}) string {
103+
104+
if len(args) == 0 {
105+
return query
106+
}
107+
108+
var sql strings.Builder
109+
replaceIndex := 0
110+
for _, v := range query {
111+
if v == '?' {
112+
if len(args) > replaceIndex {
113+
sql.WriteString(Escape(args[replaceIndex]))
114+
replaceIndex++
115+
continue
116+
}
117+
}
118+
sql.WriteRune(v)
119+
}
120+
return sql.String()
121+
}
122+
123+
//Format format the sql with args
124+
func FormatInLocation(query string, loc *time.Location, args ...interface{}) string {
125+
126+
if len(args) == 0 {
127+
return query
128+
}
129+
130+
var sql strings.Builder
131+
replaceIndex := 0
132+
for _, v := range query {
133+
if v == '?' {
134+
if len(args) > replaceIndex {
135+
sql.WriteString(EscapeInLocation(args[replaceIndex], loc))
136+
replaceIndex++
137+
continue
138+
}
139+
}
140+
sql.WriteRune(v)
141+
}
142+
return sql.String()
143+
}

0 commit comments

Comments
 (0)