~vtuson/scopecreator/twitter-template

« back to all changes in this revision

Viewing changes to src/go/src/github.com/ziutek/mymysql/native/paramvalue.go

  • Committer: Victor Palau
  • Date: 2015-03-11 14:24:42 UTC
  • Revision ID: vtuson@gmail.com-20150311142442-f2pxp111c8ynv232
public release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package native
 
2
 
 
3
import (
 
4
        "github.com/ziutek/mymysql/mysql"
 
5
        "math"
 
6
        "reflect"
 
7
        "time"
 
8
)
 
9
 
 
10
type paramValue struct {
 
11
        typ    uint16
 
12
        addr   reflect.Value
 
13
        raw    bool
 
14
        length int // >=0 - length of value, <0 - unknown length
 
15
}
 
16
 
 
17
func (val *paramValue) Len() int {
 
18
        if !val.addr.IsValid() {
 
19
                // Invalid Value was binded
 
20
                return 0
 
21
        }
 
22
        // val.addr always points to the pointer - lets dereference it
 
23
        v := val.addr.Elem()
 
24
        if v.IsNil() {
 
25
                // Binded Ptr Value is nil
 
26
                return 0
 
27
        }
 
28
        v = v.Elem()
 
29
 
 
30
        if val.length >= 0 {
 
31
                return val.length
 
32
        }
 
33
 
 
34
        switch val.typ {
 
35
        case MYSQL_TYPE_STRING:
 
36
                return lenStr(v.String())
 
37
 
 
38
        case MYSQL_TYPE_DATE:
 
39
                return lenDate(v.Interface().(mysql.Date))
 
40
 
 
41
        case MYSQL_TYPE_TIMESTAMP:
 
42
                return lenTime(v.Interface().(mysql.Timestamp).Time)
 
43
        case MYSQL_TYPE_DATETIME:
 
44
                return lenTime(v.Interface().(time.Time))
 
45
 
 
46
        case MYSQL_TYPE_TIME:
 
47
                return lenDuration(v.Interface().(time.Duration))
 
48
 
 
49
        case MYSQL_TYPE_TINY: // val.length < 0 so this is bool
 
50
                return 1
 
51
        }
 
52
        // MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_BLOB and type of Raw value
 
53
        return lenBin(v.Bytes())
 
54
}
 
55
 
 
56
func (pw *pktWriter) writeValue(val *paramValue) {
 
57
        if !val.addr.IsValid() {
 
58
                // Invalid Value was binded
 
59
                return
 
60
        }
 
61
        // val.addr always points to the pointer - lets dereference it
 
62
        v := val.addr.Elem()
 
63
        if v.IsNil() {
 
64
                // Binded Ptr Value is nil
 
65
                return
 
66
        }
 
67
        v = v.Elem()
 
68
 
 
69
        if val.raw || val.typ == MYSQL_TYPE_VAR_STRING ||
 
70
                val.typ == MYSQL_TYPE_BLOB {
 
71
                pw.writeBin(v.Bytes())
 
72
                return
 
73
        }
 
74
        // We don't need unsigned bit to check type
 
75
        unsign := (val.typ & MYSQL_UNSIGNED_MASK) != 0
 
76
        switch val.typ & ^MYSQL_UNSIGNED_MASK {
 
77
        case MYSQL_TYPE_NULL:
 
78
                // Don't write null values
 
79
 
 
80
        case MYSQL_TYPE_STRING:
 
81
                pw.writeBin([]byte(v.String()))
 
82
 
 
83
        case MYSQL_TYPE_LONG:
 
84
                i := v.Interface()
 
85
                if unsign {
 
86
                        l, ok := i.(uint32)
 
87
                        if !ok {
 
88
                                l = uint32(i.(uint))
 
89
                        }
 
90
                        pw.writeU32(l)
 
91
                } else {
 
92
                        l, ok := i.(int32)
 
93
                        if !ok {
 
94
                                l = int32(i.(int))
 
95
                        }
 
96
                        pw.writeU32(uint32(l))
 
97
                }
 
98
 
 
99
        case MYSQL_TYPE_FLOAT:
 
100
                pw.writeU32(math.Float32bits(v.Interface().(float32)))
 
101
 
 
102
        case MYSQL_TYPE_SHORT:
 
103
                if unsign {
 
104
                        pw.writeU16(v.Interface().(uint16))
 
105
                } else {
 
106
                        pw.writeU16(uint16(v.Interface().(int16)))
 
107
 
 
108
                }
 
109
 
 
110
        case MYSQL_TYPE_TINY:
 
111
                if val.length == -1 {
 
112
                        // Translate bool value to MySQL tiny
 
113
                        if v.Bool() {
 
114
                                pw.writeByte(1)
 
115
                        } else {
 
116
                                pw.writeByte(0)
 
117
                        }
 
118
                } else {
 
119
                        if unsign {
 
120
                                pw.writeByte(v.Interface().(uint8))
 
121
                        } else {
 
122
                                pw.writeByte(uint8(v.Interface().(int8)))
 
123
                        }
 
124
                }
 
125
 
 
126
        case MYSQL_TYPE_LONGLONG:
 
127
                i := v.Interface()
 
128
                if unsign {
 
129
                        l, ok := i.(uint64)
 
130
                        if !ok {
 
131
                                l = uint64(i.(uint))
 
132
                        }
 
133
                        pw.writeU64(l)
 
134
                } else {
 
135
                        l, ok := i.(int64)
 
136
                        if !ok {
 
137
                                l = int64(i.(int))
 
138
                        }
 
139
                        pw.writeU64(uint64(l))
 
140
                }
 
141
 
 
142
        case MYSQL_TYPE_DOUBLE:
 
143
                pw.writeU64(math.Float64bits(v.Interface().(float64)))
 
144
 
 
145
        case MYSQL_TYPE_DATE:
 
146
                pw.writeDate(v.Interface().(mysql.Date))
 
147
 
 
148
        case MYSQL_TYPE_TIMESTAMP:
 
149
                pw.writeTime(v.Interface().(mysql.Timestamp).Time)
 
150
 
 
151
        case MYSQL_TYPE_DATETIME:
 
152
                pw.writeTime(v.Interface().(time.Time))
 
153
 
 
154
        case MYSQL_TYPE_TIME:
 
155
                pw.writeDuration(v.Interface().(time.Duration))
 
156
 
 
157
        default:
 
158
                panic(mysql.ErrBindUnkType)
 
159
        }
 
160
        return
 
161
}