forked from uptrace/bun
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsqltype.go
141 lines (125 loc) · 3.25 KB
/
sqltype.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package schema
import (
"bytes"
"database/sql"
"encoding/json"
"reflect"
"time"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/sqltype"
"github.com/uptrace/bun/internal"
)
var (
bunNullTimeType = reflect.TypeOf((*NullTime)(nil)).Elem()
nullTimeType = reflect.TypeOf((*sql.NullTime)(nil)).Elem()
nullBoolType = reflect.TypeOf((*sql.NullBool)(nil)).Elem()
nullFloatType = reflect.TypeOf((*sql.NullFloat64)(nil)).Elem()
nullIntType = reflect.TypeOf((*sql.NullInt64)(nil)).Elem()
nullStringType = reflect.TypeOf((*sql.NullString)(nil)).Elem()
)
var sqlTypes = []string{
reflect.Bool: sqltype.Boolean,
reflect.Int: sqltype.BigInt,
reflect.Int8: sqltype.SmallInt,
reflect.Int16: sqltype.SmallInt,
reflect.Int32: sqltype.Integer,
reflect.Int64: sqltype.BigInt,
reflect.Uint: sqltype.BigInt,
reflect.Uint8: sqltype.SmallInt,
reflect.Uint16: sqltype.SmallInt,
reflect.Uint32: sqltype.Integer,
reflect.Uint64: sqltype.BigInt,
reflect.Uintptr: sqltype.BigInt,
reflect.Float32: sqltype.Real,
reflect.Float64: sqltype.DoublePrecision,
reflect.Complex64: "",
reflect.Complex128: "",
reflect.Array: "",
reflect.Interface: "",
reflect.Map: sqltype.VarChar,
reflect.Ptr: "",
reflect.Slice: sqltype.VarChar,
reflect.String: sqltype.VarChar,
reflect.Struct: sqltype.VarChar,
}
func DiscoverSQLType(typ reflect.Type) string {
switch typ {
case timeType, nullTimeType, bunNullTimeType:
return sqltype.Timestamp
case nullBoolType:
return sqltype.Boolean
case nullFloatType:
return sqltype.DoublePrecision
case nullIntType:
return sqltype.BigInt
case nullStringType:
return sqltype.VarChar
case jsonRawMessageType:
return sqltype.JSON
}
switch typ.Kind() {
case reflect.Slice:
if typ.Elem().Kind() == reflect.Uint8 {
return sqltype.Blob
}
}
return sqlTypes[typ.Kind()]
}
//------------------------------------------------------------------------------
var jsonNull = []byte("null")
// NullTime is a time.Time wrapper that marshals zero time as JSON null and SQL NULL.
type NullTime struct {
time.Time
}
var (
_ json.Marshaler = (*NullTime)(nil)
_ json.Unmarshaler = (*NullTime)(nil)
_ sql.Scanner = (*NullTime)(nil)
_ QueryAppender = (*NullTime)(nil)
)
func (tm NullTime) MarshalJSON() ([]byte, error) {
if tm.IsZero() {
return jsonNull, nil
}
return tm.Time.MarshalJSON()
}
func (tm *NullTime) UnmarshalJSON(b []byte) error {
if bytes.Equal(b, jsonNull) {
tm.Time = time.Time{}
return nil
}
return tm.Time.UnmarshalJSON(b)
}
func (tm NullTime) AppendQuery(fmter Formatter, b []byte) ([]byte, error) {
if tm.IsZero() {
return dialect.AppendNull(b), nil
}
return fmter.Dialect().AppendTime(b, tm.Time), nil
}
func (tm *NullTime) Scan(src interface{}) error {
if src == nil {
tm.Time = time.Time{}
return nil
}
switch src := src.(type) {
case time.Time:
tm.Time = src
return nil
case string:
newtm, err := internal.ParseTime(src)
if err != nil {
return err
}
tm.Time = newtm
return nil
case []byte:
newtm, err := internal.ParseTime(internal.String(src))
if err != nil {
return err
}
tm.Time = newtm
return nil
default:
return scanError(bunNullTimeType, src)
}
}