This repository has been archived by the owner on Jan 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathconnection.go
158 lines (135 loc) · 2.99 KB
/
connection.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2013 Julien Schmidt. All rights reserved.
// http://www.julienschmidt.com
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package sphinxql
import (
"database/sql/driver"
"errors"
"net"
"strings"
)
type sphinxqlConn struct {
cfg *config
flags clientFlag
charset byte
cipher []byte
netConn net.Conn
buf *buffer
protocol uint8
sequence uint8
affectedRows uint64
insertId uint64
}
type config struct {
user string
passwd string
net string
addr string
dbname string
params map[string]string
}
// Handles parameters set in DSN
func (mc *sphinxqlConn) handleParams() (err error) {
for param, val := range mc.cfg.params {
switch param {
// Charset
case "charset":
charsets := strings.Split(val, ",")
for _, charset := range charsets {
err = mc.exec("SET NAMES " + charset)
if err != nil {
return
}
}
// Timeout - already handled on connecting
case "timeout":
continue
// System Vars
default:
err = mc.exec("SET " + param + "=" + val + "")
if err != nil {
return
}
}
}
return
}
func (mc *sphinxqlConn) Begin() (driver.Tx, error) {
err := mc.exec("START TRANSACTION")
if err == nil {
return &sphinxqlTx{mc}, err
}
return nil, err
}
func (mc *sphinxqlConn) Close() (err error) {
mc.writeCommandPacket(comQuit)
mc.cfg = nil
mc.buf = nil
mc.netConn.Close()
mc.netConn = nil
return
}
func (mc *sphinxqlConn) Prepare(query string) (driver.Stmt, error) {
return &sphinxqlStmt{
mc: mc,
query: query,
}, nil
}
func (mc *sphinxqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
if len(args) == 0 {
mc.affectedRows = 0
mc.insertId = 0
err := mc.exec(query)
if err == nil {
return &sphinxqlResult{
affectedRows: int64(mc.affectedRows),
insertId: int64(mc.insertId),
}, err
}
return nil, err
}
return nil, errors.New("args not supported")
}
// Internal function to execute commands
func (mc *sphinxqlConn) exec(query string) (err error) {
// Send command
err = mc.writeCommandPacketStr(comQuery, query)
if err != nil {
return
}
// Read Result
var resLen int
resLen, err = mc.readResultSetHeaderPacket()
if err == nil && resLen > 0 {
err = mc.readUntilEOF()
if err != nil {
return
}
err = mc.readUntilEOF()
}
return
}
func (mc *sphinxqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
if len(args) == 0 {
// Send command
err := mc.writeCommandPacketStr(comQuery, query)
if err == nil {
// Read Result
var resLen int
resLen, err = mc.readResultSetHeaderPacket()
if err == nil {
rows := &sphinxqlRows{mc, nil, false}
if resLen > 0 {
// Columns
rows.columns, err = mc.readColumns(resLen)
}
return rows, err
}
}
return nil, err
}
return nil, errors.New("args not supported")
}