~vtuson/scopecreator/twitter-template

« back to all changes in this revision

Viewing changes to src/go/src/github.com/ziutek/mymysql/native/prepared.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
        "log"
 
6
)
 
7
 
 
8
type Stmt struct {
 
9
        my *Conn
 
10
 
 
11
        id  uint32
 
12
        sql string // For reprepare during reconnect
 
13
 
 
14
        params []paramValue // Parameters binding
 
15
        rebind bool
 
16
        binded bool
 
17
 
 
18
        fields []*mysql.Field
 
19
 
 
20
        field_count   int
 
21
        param_count   int
 
22
        warning_count int
 
23
        status        uint16
 
24
 
 
25
        null_bitmap []byte
 
26
}
 
27
 
 
28
func (stmt *Stmt) Fields() []*mysql.Field {
 
29
        return stmt.fields
 
30
}
 
31
 
 
32
func (stmt *Stmt) NumParam() int {
 
33
        return stmt.param_count
 
34
}
 
35
 
 
36
func (stmt *Stmt) WarnCount() int {
 
37
        return stmt.warning_count
 
38
}
 
39
 
 
40
func (stmt *Stmt) sendCmdExec() {
 
41
        // Calculate packet length and NULL bitmap
 
42
        pkt_len := 1 + 4 + 1 + 4 + 1 + len(stmt.null_bitmap)
 
43
        for ii, param := range stmt.params {
 
44
                par_len := param.Len()
 
45
                pkt_len += par_len
 
46
                if par_len == 0 {
 
47
                        null_byte := ii >> 3
 
48
                        null_mask := byte(1) << uint(ii-(null_byte<<3))
 
49
                        stmt.null_bitmap[null_byte] |= null_mask
 
50
                }
 
51
        }
 
52
        if stmt.rebind {
 
53
                pkt_len += stmt.param_count * 2
 
54
        }
 
55
        // Reset sequence number
 
56
        stmt.my.seq = 0
 
57
        // Packet sending
 
58
        pw := stmt.my.newPktWriter(pkt_len)
 
59
        pw.writeByte(_COM_STMT_EXECUTE)
 
60
        pw.writeU32(stmt.id)
 
61
        pw.writeByte(0) // flags = CURSOR_TYPE_NO_CURSOR
 
62
        pw.writeU32(1)  // iteration_count
 
63
        pw.write(stmt.null_bitmap)
 
64
        if stmt.rebind {
 
65
                pw.writeByte(1)
 
66
                // Types
 
67
                for _, param := range stmt.params {
 
68
                        pw.writeU16(param.typ)
 
69
                }
 
70
        } else {
 
71
                pw.writeByte(0)
 
72
        }
 
73
        // Values
 
74
        for i := range stmt.params {
 
75
                pw.writeValue(&stmt.params[i])
 
76
        }
 
77
 
 
78
        if stmt.my.Debug {
 
79
                log.Printf("[%2d <-] Exec command packet: len=%d, null_bitmap=%v, rebind=%t",
 
80
                        stmt.my.seq-1, pkt_len, stmt.null_bitmap, stmt.rebind)
 
81
        }
 
82
 
 
83
        // Mark that we sended information about binded types
 
84
        stmt.rebind = false
 
85
}
 
86
 
 
87
func (my *Conn) getPrepareResult(stmt *Stmt) interface{} {
 
88
loop:
 
89
        pr := my.newPktReader() // New reader for next packet
 
90
        pkt0 := pr.readByte()
 
91
 
 
92
        //log.Println("pkt0:", pkt0, "stmt:", stmt)
 
93
 
 
94
        if pkt0 == 255 {
 
95
                // Error packet
 
96
                my.getErrorPacket(pr)
 
97
        }
 
98
 
 
99
        if stmt == nil {
 
100
                if pkt0 == 0 {
 
101
                        // OK packet
 
102
                        return my.getPrepareOkPacket(pr)
 
103
                }
 
104
        } else {
 
105
                unreaded_params := (stmt.param_count < len(stmt.params))
 
106
                switch {
 
107
                case pkt0 == 254:
 
108
                        // EOF packet
 
109
                        stmt.warning_count, stmt.status = my.getEofPacket(pr)
 
110
                        stmt.my.status = stmt.status
 
111
                        return stmt
 
112
 
 
113
                case pkt0 > 0 && pkt0 < 251 && (stmt.field_count < len(stmt.fields) ||
 
114
                        unreaded_params):
 
115
                        // Field packet
 
116
                        if unreaded_params {
 
117
                                // Read and ignore parameter field. Sentence from MySQL source:
 
118
                                /* skip parameters data: we don't support it yet */
 
119
                                pr.skipAll()
 
120
                                // Increment param_count count
 
121
                                stmt.param_count++
 
122
                        } else {
 
123
                                field := my.getFieldPacket(pr)
 
124
                                stmt.fields[stmt.field_count] = field
 
125
                                // Increment field count
 
126
                                stmt.field_count++
 
127
                        }
 
128
                        // Read next packet
 
129
                        goto loop
 
130
                }
 
131
        }
 
132
        panic(mysql.ErrUnkResultPkt)
 
133
}
 
134
 
 
135
func (my *Conn) getPrepareOkPacket(pr *pktReader) (stmt *Stmt) {
 
136
        if my.Debug {
 
137
                log.Printf("[%2d ->] Perpared OK packet:", my.seq-1)
 
138
        }
 
139
 
 
140
        stmt = new(Stmt)
 
141
        stmt.my = my
 
142
        // First byte was readed by getPrepRes
 
143
        stmt.id = pr.readU32()
 
144
        stmt.fields = make([]*mysql.Field, int(pr.readU16())) // FieldCount
 
145
        pl := int(pr.readU16())                               // ParamCount
 
146
        if pl > 0 {
 
147
                stmt.params = make([]paramValue, pl)
 
148
                stmt.null_bitmap = make([]byte, (pl+7)>>3)
 
149
        }
 
150
        pr.skipN(1)
 
151
        stmt.warning_count = int(pr.readU16())
 
152
        pr.checkEof()
 
153
 
 
154
        if my.Debug {
 
155
                log.Printf(tab8s+"ID=0x%x ParamCount=%d FieldsCount=%d WarnCount=%d",
 
156
                        stmt.id, len(stmt.params), len(stmt.fields), stmt.warning_count,
 
157
                )
 
158
        }
 
159
        return
 
160
}