File: binding.go

package info (click to toggle)
golang-github-ziutek-mymysql 1.5.4%2Bgit20170206.23.0582bcf-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 388 kB
  • sloc: makefile: 8; sh: 2
file content (150 lines) | stat: -rw-r--r-- 2,993 bytes parent folder | download
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
142
143
144
145
146
147
148
149
150
package native

import (
	"github.com/ziutek/mymysql/mysql"
	"reflect"
	"time"
)

var (
	timeType      = reflect.TypeOf(time.Time{})
	timestampType = reflect.TypeOf(mysql.Timestamp{})
	dateType      = reflect.TypeOf(mysql.Date{})
	durationType  = reflect.TypeOf(time.Duration(0))
	blobType      = reflect.TypeOf(mysql.Blob{})
	rawType       = reflect.TypeOf(mysql.Raw{})
)

// val should be an addressable value
func bindValue(val reflect.Value) (out paramValue) {
	if !val.IsValid() {
		out.typ = MYSQL_TYPE_NULL
		return
	}
	typ := val.Type()
	if typ.Kind() == reflect.Ptr {
		// We have addressable pointer
		out.addr = val.Addr()
		// Dereference pointer for next operation on its value
		typ = typ.Elem()
		val = val.Elem()
	} else {
		// We have addressable value. Create a pointer to it
		pv := val.Addr()
		// This pointer is unaddressable so copy it and return an address
		out.addr = reflect.New(pv.Type())
		out.addr.Elem().Set(pv)
	}

	// Obtain value type
	switch typ.Kind() {
	case reflect.String:
		out.typ = MYSQL_TYPE_STRING
		out.length = -1
		return

	case reflect.Int:
		out.typ = _INT_TYPE
		out.length = _SIZE_OF_INT
		return

	case reflect.Int8:
		out.typ = MYSQL_TYPE_TINY
		out.length = 1
		return

	case reflect.Int16:
		out.typ = MYSQL_TYPE_SHORT
		out.length = 2
		return

	case reflect.Int32:
		out.typ = MYSQL_TYPE_LONG
		out.length = 4
		return

	case reflect.Int64:
		if typ == durationType {
			out.typ = MYSQL_TYPE_TIME
			out.length = -1
			return
		}
		out.typ = MYSQL_TYPE_LONGLONG
		out.length = 8
		return

	case reflect.Uint:
		out.typ = _INT_TYPE | MYSQL_UNSIGNED_MASK
		out.length = _SIZE_OF_INT
		return

	case reflect.Uint8:
		out.typ = MYSQL_TYPE_TINY | MYSQL_UNSIGNED_MASK
		out.length = 1
		return

	case reflect.Uint16:
		out.typ = MYSQL_TYPE_SHORT | MYSQL_UNSIGNED_MASK
		out.length = 2
		return

	case reflect.Uint32:
		out.typ = MYSQL_TYPE_LONG | MYSQL_UNSIGNED_MASK
		out.length = 4
		return

	case reflect.Uint64:
		out.typ = MYSQL_TYPE_LONGLONG | MYSQL_UNSIGNED_MASK
		out.length = 8
		return

	case reflect.Float32:
		out.typ = MYSQL_TYPE_FLOAT
		out.length = 4
		return

	case reflect.Float64:
		out.typ = MYSQL_TYPE_DOUBLE
		out.length = 8
		return

	case reflect.Slice:
		out.length = -1
		if typ == blobType {
			out.typ = MYSQL_TYPE_BLOB
			return
		}
		if typ.Elem().Kind() == reflect.Uint8 {
			out.typ = MYSQL_TYPE_VAR_STRING
			return
		}

	case reflect.Struct:
		out.length = -1
		if typ == timeType {
			out.typ = MYSQL_TYPE_DATETIME
			return
		}
		if typ == dateType {
			out.typ = MYSQL_TYPE_DATE
			return
		}
		if typ == timestampType {
			out.typ = MYSQL_TYPE_TIMESTAMP
			return
		}
		if typ == rawType {
			out.typ = val.FieldByName("Typ").Interface().(uint16)
			out.addr = val.FieldByName("Val").Addr()
			out.raw = true
			return
		}

	case reflect.Bool:
		out.typ = MYSQL_TYPE_TINY
		// bool implementation isn't documented so we treat it in special way
		out.length = -1
		return
	}
	panic(mysql.ErrBindUnkType)
}