Skip to content

Commit b488e03

Browse files
authored
Merge branch 'master' into master
2 parents a9bdb59 + 8253e51 commit b488e03

File tree

9 files changed

+362
-21
lines changed

9 files changed

+362
-21
lines changed

client/auth.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,18 @@ func (c *Conn) writeAuthHandshake() error {
140140
if !authPluginAllowed(c.authPluginName) {
141141
return fmt.Errorf("unknow auth plugin name '%s'", c.authPluginName)
142142
}
143-
// Adjust client capability flags based on server support
143+
144+
// Set default client capabilities that reflect the abilities of this library
144145
capability := CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION |
145-
CLIENT_LONG_PASSWORD | CLIENT_TRANSACTIONS | CLIENT_PLUGIN_AUTH | c.capability&CLIENT_LONG_FLAG
146+
CLIENT_LONG_PASSWORD | CLIENT_TRANSACTIONS | CLIENT_PLUGIN_AUTH
147+
// Adjust client capability flags based on server support
148+
capability |= c.capability & CLIENT_LONG_FLAG
149+
// Adjust client capability flags on specific client requests
150+
// Only flags that would make any sense setting and aren't handled elsewhere
151+
// in the library are supported here
152+
capability |= c.ccaps&CLIENT_FOUND_ROWS | c.ccaps&CLIENT_IGNORE_SPACE |
153+
c.ccaps&CLIENT_MULTI_STATEMENTS | c.ccaps&CLIENT_MULTI_RESULTS |
154+
c.ccaps&CLIENT_PS_MULTI_RESULTS | c.ccaps&CLIENT_CONNECT_ATTRS
146155

147156
// To enable TLS / SSL
148157
if c.tlsConfig != nil {

client/client_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,41 @@ func (s *clientTestSuite) TestConn_Ping(c *C) {
9494
c.Assert(err, IsNil)
9595
}
9696

97+
func (s *clientTestSuite) TestConn_SetCapability(c *C) {
98+
caps := []uint32{
99+
mysql.CLIENT_LONG_PASSWORD,
100+
mysql.CLIENT_FOUND_ROWS,
101+
mysql.CLIENT_LONG_FLAG,
102+
mysql.CLIENT_CONNECT_WITH_DB,
103+
mysql.CLIENT_NO_SCHEMA,
104+
mysql.CLIENT_COMPRESS,
105+
mysql.CLIENT_ODBC,
106+
mysql.CLIENT_LOCAL_FILES,
107+
mysql.CLIENT_IGNORE_SPACE,
108+
mysql.CLIENT_PROTOCOL_41,
109+
mysql.CLIENT_INTERACTIVE,
110+
mysql.CLIENT_SSL,
111+
mysql.CLIENT_IGNORE_SIGPIPE,
112+
mysql.CLIENT_TRANSACTIONS,
113+
mysql.CLIENT_RESERVED,
114+
mysql.CLIENT_SECURE_CONNECTION,
115+
mysql.CLIENT_MULTI_STATEMENTS,
116+
mysql.CLIENT_MULTI_RESULTS,
117+
mysql.CLIENT_PS_MULTI_RESULTS,
118+
mysql.CLIENT_PLUGIN_AUTH,
119+
mysql.CLIENT_CONNECT_ATTRS,
120+
mysql.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA,
121+
}
122+
123+
for _, cap := range caps {
124+
c.Assert(s.c.ccaps&cap > 0, IsFalse)
125+
s.c.SetCapability(cap)
126+
c.Assert(s.c.ccaps&cap > 0, IsTrue)
127+
s.c.UnsetCapability(cap)
128+
c.Assert(s.c.ccaps&cap > 0, IsFalse)
129+
}
130+
}
131+
97132
// NOTE for MySQL 5.5 and 5.6, server side has to config SSL to pass the TLS test, otherwise, it will throw error that
98133
// MySQL server does not support TLS required by the client. However, for MySQL 5.7 and above, auto generated certificates
99134
// are used by default so that manual config is no longer necessary.

client/conn.go

+13
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ type Conn struct {
2121
tlsConfig *tls.Config
2222
proto string
2323

24+
// server capabilities
2425
capability uint32
26+
// client-set capabilities only
27+
ccaps uint32
2528

2629
status uint16
2730

@@ -120,6 +123,16 @@ func (c *Conn) Ping() error {
120123
return nil
121124
}
122125

126+
// SetCapability enables the use of a specific capability
127+
func (c *Conn) SetCapability(cap uint32) {
128+
c.ccaps |= cap
129+
}
130+
131+
// UnsetCapability disables the use of a specific capability
132+
func (c *Conn) UnsetCapability(cap uint32) {
133+
c.ccaps &= ^cap
134+
}
135+
123136
// UseSSL: use default SSL
124137
// pass to options when connect
125138
func (c *Conn) UseSSL(insecureSkipVerify bool) {

cmd/go-mysqlbinlog/main.go

+22-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var flavor = flag.String("flavor", "mysql", "Flavor: mysql or mariadb")
2424

2525
var file = flag.String("file", "", "Binlog filename")
2626
var pos = flag.Int("pos", 4, "Binlog position")
27+
var gtid = flag.String("gtid", "", "Binlog GTID set that this slave has executed")
2728

2829
var semiSync = flag.Bool("semisync", false, "Support semi sync")
2930
var backupPath = flag.String("backup_path", "", "backup path to store binlog files")
@@ -57,10 +58,27 @@ func main() {
5758
return
5859
}
5960
} else {
60-
s, err := b.StartSync(pos)
61-
if err != nil {
62-
fmt.Printf("Start sync error: %v\n", errors.ErrorStack(err))
63-
return
61+
var (
62+
s *replication.BinlogStreamer
63+
err error
64+
)
65+
if len(*gtid) > 0 {
66+
gset, err := mysql.ParseGTIDSet(*flavor, *gtid)
67+
if err != nil {
68+
fmt.Printf("Failed to parse gtid %s with flavor %s, error: %v\n",
69+
*gtid, *flavor, errors.ErrorStack(err))
70+
}
71+
s, err = b.StartSyncGTID(gset)
72+
if err != nil {
73+
fmt.Printf("Start sync by GTID error: %v\n", errors.ErrorStack(err))
74+
return
75+
}
76+
} else {
77+
s, err = b.StartSync(pos)
78+
if err != nil {
79+
fmt.Printf("Start sync error: %v\n", errors.ErrorStack(err))
80+
return
81+
}
6482
}
6583

6684
for {

mysql/rowdata.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func (p RowData) ParseBinary(f []*Field, dst []FieldValue) ([]FieldValue, error)
177177
case MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
178178
MYSQL_TYPE_BIT, MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
179179
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
180-
MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY:
180+
MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_JSON:
181181
v, isNull, n, err = LengthEncodedString(p[pos:])
182182
pos += n
183183
if err != nil {

schema/schema.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ type Index struct {
5656
Name string
5757
Columns []string
5858
Cardinality []uint64
59+
NoneUnique uint64
5960
}
6061

6162
type Table struct {
@@ -190,7 +191,7 @@ func (ta *Table) AddIndex(name string) (index *Index) {
190191
}
191192

192193
func NewIndex(name string) *Index {
193-
return &Index{name, make([]string, 0, 8), make([]uint64, 0, 8)}
194+
return &Index{name, make([]string, 0, 8), make([]uint64, 0, 8), 0}
194195
}
195196

196197
func (idx *Index) AddColumn(name string, cardinality uint64) {
@@ -317,6 +318,7 @@ func (ta *Table) fetchIndexes(conn mysql.Executer) error {
317318
cardinality, _ := r.GetUint(i, 6)
318319
colName, _ := r.GetString(i, 4)
319320
currentIndex.AddColumn(colName, cardinality)
321+
currentIndex.NoneUnique, _ = r.GetUint(i, 1)
320322
}
321323

322324
return ta.fetchPrimaryKeyColumns()
@@ -338,11 +340,12 @@ func (ta *Table) fetchIndexesViaSqlDB(conn *sql.DB) error {
338340

339341
for r.Next() {
340342
var indexName, colName string
343+
var noneUnique uint64
341344
var cardinality interface{}
342345

343346
err := r.Scan(
344347
&unused,
345-
&unused,
348+
&noneUnique,
346349
&indexName,
347350
&unused,
348351
&colName,
@@ -366,6 +369,7 @@ func (ta *Table) fetchIndexesViaSqlDB(conn *sql.DB) error {
366369

367370
c := toUint64(cardinality)
368371
currentIndex.AddColumn(colName, c)
372+
currentIndex.NoneUnique = noneUnique
369373
}
370374

371375
return ta.fetchPrimaryKeyColumns()

server/resp.go

+6-12
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,7 @@ func (c *Conn) writeResultset(r *Resultset) error {
125125
return err
126126
}
127127

128-
for _, v := range r.Fields {
129-
data = data[0:4]
130-
data = append(data, v.Dump()...)
131-
if err := c.WritePacket(data); err != nil {
132-
return err
133-
}
134-
}
135-
136-
if err := c.writeEOF(); err != nil {
128+
if err := c.writeFieldList(r.Fields, data); err != nil {
137129
return err
138130
}
139131

@@ -152,8 +144,10 @@ func (c *Conn) writeResultset(r *Resultset) error {
152144
return nil
153145
}
154146

155-
func (c *Conn) writeFieldList(fs []*Field) error {
156-
data := make([]byte, 4, 1024)
147+
func (c *Conn) writeFieldList(fs []*Field, data []byte) error {
148+
if data == nil {
149+
data = make([]byte, 4, 1024)
150+
}
157151

158152
for _, v := range fs {
159153
data = data[0:4]
@@ -189,7 +183,7 @@ func (c *Conn) writeValue(value interface{}) error {
189183
return c.writeOK(v)
190184
}
191185
case []*Field:
192-
return c.writeFieldList(v)
186+
return c.writeFieldList(v, nil)
193187
case *Stmt:
194188
return c.writePrepare(v)
195189
default:

0 commit comments

Comments
 (0)