diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa7a69e9a..9f927f24d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,7 @@ jobs: with: go-version: stable - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: version: latest args: --timeout=3m diff --git a/.golangci.yml b/.golangci.yml index e57b1c253..05b322569 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,35 +1,47 @@ +version: "2" linters: - disable-all: true + default: none enable: - # All code is ready for: - errcheck - - gofumpt - - goimports - govet - - gosimple - ineffassign - misspell - nakedret - nolintlint - staticcheck - - typecheck - unconvert - unused - whitespace - # ToDo: - #- gocritic - #- golint -linters-settings: - nolintlint: - allow-unused: false - require-specific: true - - govet: - enable-all: true - disable: - - fieldalignment - - lostcancel - - shadow -issues: - exclude-files: - - client/examples_test.go + settings: + govet: + disable: + - fieldalignment + - lostcancel + - shadow + enable-all: true + nolintlint: + require-specific: true + allow-unused: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - client/examples_test.go + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - client/examples_test.go + - third_party$ + - builtin$ + - examples$ diff --git a/client/conn.go b/client/conn.go index 00b72843a..cf56399ad 100644 --- a/client/conn.go +++ b/client/conn.go @@ -152,9 +152,9 @@ func ConnectWithDialer(ctx context.Context, network, addr, user, password, dbNam c.Conn = packet.NewConnWithTimeout(conn, c.ReadTimeout, c.WriteTimeout, c.BufferSize) if c.tlsConfig != nil { - seq := c.Conn.Sequence + seq := c.Sequence c.Conn = packet.NewTLSConnWithTimeout(conn, c.ReadTimeout, c.WriteTimeout) - c.Conn.Sequence = seq + c.Sequence = seq } if err = c.handshake(); err != nil { @@ -163,9 +163,9 @@ func ConnectWithDialer(ctx context.Context, network, addr, user, password, dbNam } if c.ccaps&mysql.CLIENT_COMPRESS > 0 { - c.Conn.Compression = mysql.MYSQL_COMPRESS_ZLIB + c.Compression = mysql.MYSQL_COMPRESS_ZLIB } else if c.ccaps&mysql.CLIENT_ZSTD_COMPRESSION_ALGORITHM > 0 { - c.Conn.Compression = mysql.MYSQL_COMPRESS_ZSTD + c.Compression = mysql.MYSQL_COMPRESS_ZSTD } // if a collation was set with a ID of > 255, then we need to call SET NAMES ... diff --git a/client/conn_test.go b/client/conn_test.go index 5cb8346eb..c82010757 100644 --- a/client/conn_test.go +++ b/client/conn_test.go @@ -119,14 +119,14 @@ func (s *connTestSuite) TestExecuteMultiple() { // also, since this is not the last query, the SERVER_MORE_RESULTS_EXISTS // flag should be set require.True(s.T(), result.Status&mysql.SERVER_MORE_RESULTS_EXISTS > 0) - require.Equal(s.T(), 0, result.Resultset.RowNumber()) + require.Equal(s.T(), 0, result.RowNumber()) require.Equal(s.T(), uint64(1), result.AffectedRows) require.NoError(s.T(), err) case 1: // the SELECT query should have an resultset // still not the last query, flag should be set require.True(s.T(), result.Status&mysql.SERVER_MORE_RESULTS_EXISTS > 0) - require.Greater(s.T(), result.Resultset.RowNumber(), 0) + require.Greater(s.T(), result.RowNumber(), 0) require.NoError(s.T(), err) case 3: // this query is obviously bogus so the error should be non-nil @@ -175,7 +175,7 @@ func (s *connTestSuite) TestExecuteSelectStreaming() { // result.Resultset must be defined at this point require.NotNil(s.T(), result.Resultset) // Check number of columns - require.Len(s.T(), result.Resultset.Fields, colsInResult) + require.Len(s.T(), result.Fields, colsInResult) perResultCallbackCalledTimes++ return nil diff --git a/client/resp.go b/client/resp.go index 9aef7ab75..071aafa27 100644 --- a/client/resp.go +++ b/client/resp.go @@ -121,14 +121,16 @@ func (c *Conn) handleAuthResult() error { } // handle caching_sha2_password - if c.authPluginName == mysql.AUTH_CACHING_SHA2_PASSWORD { + switch c.authPluginName { + case mysql.AUTH_CACHING_SHA2_PASSWORD: if data == nil { return nil // auth already succeeded } - if data[0] == mysql.CACHE_SHA2_FAST_AUTH { + switch data[0] { + case mysql.CACHE_SHA2_FAST_AUTH: _, err = c.readOK() return err - } else if data[0] == mysql.CACHE_SHA2_FULL_AUTH { + case mysql.CACHE_SHA2_FULL_AUTH: // need full authentication if c.tlsConfig != nil || c.proto == "unix" { if err = c.WriteClearAuthPacket(c.password); err != nil { @@ -141,10 +143,10 @@ func (c *Conn) handleAuthResult() error { } _, err = c.readOK() return err - } else { + default: return errors.Errorf("invalid packet %x", data[0]) } - } else if c.authPluginName == mysql.AUTH_SHA256_PASSWORD { + case mysql.AUTH_SHA256_PASSWORD: if len(data) == 0 { return nil // auth already succeeded } @@ -205,11 +207,12 @@ func (c *Conn) readOK() (*mysql.Result, error) { return nil, errors.Trace(err) } - if data[0] == mysql.OK_HEADER { + switch data[0] { + case mysql.OK_HEADER: return c.handleOKPacket(data) - } else if data[0] == mysql.ERR_HEADER { + case mysql.ERR_HEADER: return nil, c.handleErrorPacket(data) - } else { + default: return nil, errors.New("invalid ok packet") } } @@ -310,7 +313,7 @@ func (c *Conn) readResultsetStreaming(data []byte, binary bool, result *mysql.Re } // this is a streaming resultset - result.Resultset.Streaming = mysql.StreamingSelect + result.Streaming = mysql.StreamingSelect if err := c.readResultColumns(result); err != nil { return errors.Trace(err) @@ -327,7 +330,7 @@ func (c *Conn) readResultsetStreaming(data []byte, binary bool, result *mysql.Re } // this resultset is done streaming - result.Resultset.StreamingDone = true + result.StreamingDone = true return nil } diff --git a/driver/driver.go b/driver/driver.go index 71827df8c..8907f1c65 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -379,7 +379,7 @@ func (st *state) replyError(err error) error { func (c *conn) Exec(query string, args []sqldriver.Value) (sqldriver.Result, error) { a := buildArgs(args) - r, err := c.Conn.Execute(query, a...) + r, err := c.Execute(query, a...) if err != nil { return nil, c.state.replyError(err) } @@ -389,7 +389,7 @@ func (c *conn) Exec(query string, args []sqldriver.Value) (sqldriver.Result, err func (c *conn) ExecContext(ctx context.Context, query string, args []sqldriver.NamedValue) (sqldriver.Result, error) { defer c.watchCtx(ctx)() a := buildNamedArgs(args) - r, err := c.Conn.Execute(query, a...) + r, err := c.Execute(query, a...) if err != nil { return nil, c.state.replyError(err) } @@ -398,7 +398,7 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []sqldriver.N func (c *conn) Query(query string, args []sqldriver.Value) (sqldriver.Rows, error) { a := buildArgs(args) - r, err := c.Conn.Execute(query, a...) + r, err := c.Execute(query, a...) if err != nil { return nil, c.state.replyError(err) } @@ -408,7 +408,7 @@ func (c *conn) Query(query string, args []sqldriver.Value) (sqldriver.Rows, erro func (c *conn) QueryContext(ctx context.Context, query string, args []sqldriver.NamedValue) (sqldriver.Rows, error) { defer c.watchCtx(ctx)() a := buildNamedArgs(args) - r, err := c.Conn.Execute(query, a...) + r, err := c.Execute(query, a...) if err != nil { return nil, c.state.replyError(err) } @@ -429,12 +429,12 @@ func (s *stmt) Close() error { } func (s *stmt) NumInput() int { - return s.Stmt.ParamNum() + return s.ParamNum() } func (s *stmt) Exec(args []sqldriver.Value) (sqldriver.Result, error) { a := buildArgs(args) - r, err := s.Stmt.Execute(a...) + r, err := s.Execute(a...) if err != nil { return nil, s.connectionState.replyError(err) } @@ -445,7 +445,7 @@ func (s *stmt) ExecContext(ctx context.Context, args []sqldriver.NamedValue) (sq defer s.watchCtx(ctx)() a := buildNamedArgs(args) - r, err := s.Stmt.Execute(a...) + r, err := s.Execute(a...) if err != nil { return nil, s.connectionState.replyError(err) } @@ -454,7 +454,7 @@ func (s *stmt) ExecContext(ctx context.Context, args []sqldriver.NamedValue) (sq func (s *stmt) Query(args []sqldriver.Value) (sqldriver.Rows, error) { a := buildArgs(args) - r, err := s.Stmt.Execute(a...) + r, err := s.Execute(a...) if err != nil { return nil, s.connectionState.replyError(err) } @@ -465,7 +465,7 @@ func (s *stmt) QueryContext(ctx context.Context, args []sqldriver.NamedValue) (s defer s.watchCtx(ctx)() a := buildNamedArgs(args) - r, err := s.Stmt.Execute(a...) + r, err := s.Execute(a...) if err != nil { return nil, s.connectionState.replyError(err) } @@ -489,11 +489,11 @@ type result struct { } func (r *result) LastInsertId() (int64, error) { - return int64(r.Result.InsertId), nil + return int64(r.InsertId), nil } func (r *result) RowsAffected() (int64, error) { - return int64(r.Result.AffectedRows), nil + return int64(r.AffectedRows), nil } type rows struct { @@ -531,14 +531,14 @@ func (r *rows) Close() error { } func (r *rows) Next(dest []sqldriver.Value) error { - if r.step >= r.Resultset.RowNumber() { + if r.step >= r.RowNumber() { return io.EOF } else if r.step == -1 { return io.ErrUnexpectedEOF } - for i := 0; i < r.Resultset.ColumnNumber(); i++ { - value, err := r.Resultset.GetValue(r.step, i) + for i := 0; i < r.ColumnNumber(); i++ { + value, err := r.GetValue(r.step, i) if err != nil { return err } diff --git a/dump/dumper.go b/dump/dumper.go index b10d810ae..3976f2c9f 100644 --- a/dump/dumper.go +++ b/dump/dumper.go @@ -303,7 +303,7 @@ func (d *Dumper) Dump(w io.Writer) error { // If we only dump some tables, the dump data will not have database name // which makes us hard to parse, so here we add it manually. - _, err := w.Write([]byte(fmt.Sprintf("USE `%s`;\n", d.TableDB))) + _, err := fmt.Fprintf(w, "USE `%s`;\n", d.TableDB) if err != nil { return fmt.Errorf(`could not write USE command: %w`, err) } diff --git a/mysql/result.go b/mysql/result.go index f103194b3..1ae1ca926 100644 --- a/mysql/result.go +++ b/mysql/result.go @@ -30,7 +30,7 @@ type Executer interface { func (r *Result) Close() { if r.Resultset != nil { - r.Resultset.returnToPool() + r.returnToPool() r.Resultset = nil } } @@ -39,7 +39,7 @@ func (r *Result) HasResultset() bool { if r == nil { return false } - if r.Resultset != nil && len(r.Resultset.Fields) > 0 { + if r.Resultset != nil && len(r.Fields) > 0 { return true } return false diff --git a/replication/backup.go b/replication/backup.go index 08f47473f..5640dbd0a 100644 --- a/replication/backup.go +++ b/replication/backup.go @@ -146,14 +146,15 @@ func (h *BackupEventHandler) HandleEvent(e *BinlogEvent) error { var err error offset := e.Header.LogPos - if e.Header.EventType == ROTATE_EVENT { + switch e.Header.EventType { + case ROTATE_EVENT: rotateEvent := e.Event.(*RotateEvent) h.filename = string(rotateEvent.NextLogName) if e.Header.Timestamp == 0 || offset == 0 { // fake rotate event return nil } - } else if e.Header.EventType == FORMAT_DESCRIPTION_EVENT { + case FORMAT_DESCRIPTION_EVENT: if h.w != nil { if err = h.w.Close(); err != nil { h.w = nil diff --git a/replication/binlogsyncer.go b/replication/binlogsyncer.go index 612229926..90aa1e34b 100644 --- a/replication/binlogsyncer.go +++ b/replication/binlogsyncer.go @@ -722,7 +722,7 @@ func (b *BinlogSyncer) prepareSyncGTID(gset mysql.GTIDSet) error { func (b *BinlogSyncer) onStream(s *BinlogStreamer) { defer func() { if e := recover(); e != nil { - s.closeWithError(fmt.Errorf("Err: %v\n Stack: %s", e, mysql.Pstack())) + s.closeWithError(fmt.Errorf("panic %v\nstack: %s", e, mysql.Pstack())) } b.wg.Done() }() diff --git a/replication/parser.go b/replication/parser.go index eedc205ae..f66345588 100644 --- a/replication/parser.go +++ b/replication/parser.go @@ -165,11 +165,7 @@ func (p *BinlogParser) parseSingleEvent(r io.Reader, onEvent OnEventFunc) (bool, } func (p *BinlogParser) ParseReader(r io.Reader, onEvent OnEventFunc) error { - for { - if atomic.LoadUint32(&p.stopProcessing) == 1 { - break - } - + for atomic.LoadUint32(&p.stopProcessing) != 1 { done, err := p.parseSingleEvent(r, onEvent) if err != nil { if err == errMissingTableMapEvent { diff --git a/replication/row_event.go b/replication/row_event.go index 3883ae1dc..6fc943dd8 100644 --- a/replication/row_event.go +++ b/replication/row_event.go @@ -1060,7 +1060,7 @@ func (e *RowsEvent) decodeExtraData(data []byte) (err2 error) { pos += 1 switch extraDataType { case ENUM_EXTRA_ROW_INFO_TYPECODE_NDB: - var ndbLength int = int(data[pos]) + ndbLength := int(data[pos]) pos += 1 e.NdbFormat = data[pos] pos += 1 @@ -1388,7 +1388,7 @@ func (e *RowsEvent) decodeValue(data []byte, tp byte, meta uint16, isPartial boo v = int64(binary.LittleEndian.Uint16(data)) n = 2 default: - err = fmt.Errorf("Unknown ENUM packlen=%d", l) + err = fmt.Errorf("unknown ENUM packlen=%d", l) } case mysql.MYSQL_TYPE_SET: n = int(meta & 0xFF) diff --git a/schema/schema.go b/schema/schema.go index 3adcde4d3..4a0894c85 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -89,21 +89,21 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext ta.Columns[index].Type = TYPE_DECIMAL } else if strings.HasPrefix(columnType, "enum") { ta.Columns[index].Type = TYPE_ENUM - ta.Columns[index].EnumValues = strings.Split(strings.Replace( + ta.Columns[index].EnumValues = strings.Split(strings.ReplaceAll( strings.TrimSuffix( strings.TrimPrefix( columnType, "enum("), ")"), - "'", "", -1), + "'", ""), ",") } else if strings.HasPrefix(columnType, "set") { ta.Columns[index].Type = TYPE_SET - ta.Columns[index].SetValues = strings.Split(strings.Replace( + ta.Columns[index].SetValues = strings.Split(strings.ReplaceAll( strings.TrimSuffix( strings.TrimPrefix( columnType, "set("), ")"), - "'", "", -1), + "'", ""), ",") } else if strings.HasPrefix(columnType, "binary") { ta.Columns[index].Type = TYPE_BINARY @@ -119,7 +119,7 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext ta.Columns[index].Type = TYPE_TIMESTAMP } else if strings.HasPrefix(columnType, "time") { ta.Columns[index].Type = TYPE_TIME - } else if "date" == columnType { + } else if columnType == "date" { ta.Columns[index].Type = TYPE_DATE } else if strings.HasPrefix(columnType, "bit") { ta.Columns[index].Type = TYPE_BIT @@ -146,11 +146,12 @@ func (ta *Table) AddColumn(name string, columnType string, collation string, ext ta.UnsignedColumns = append(ta.UnsignedColumns, index) } - if extra == "auto_increment" { + switch extra { + case "auto_increment": ta.Columns[index].IsAuto = true - } else if extra == "VIRTUAL GENERATED" { + case "VIRTUAL GENERATED": ta.Columns[index].IsVirtual = true - } else if extra == "STORED GENERATED" { + case "STORED GENERATED": ta.Columns[index].IsStored = true } } diff --git a/server/auth.go b/server/auth.go index 0fcf8f1ee..9d1f8101c 100644 --- a/server/auth.go +++ b/server/auth.go @@ -168,7 +168,7 @@ func (c *Conn) compareCacheSha2PasswordAuthData(clientAuthData []byte) error { return errAccessDenied(c.password) } // other type of credential provider, we use the cache - cached, ok := c.serverConf.cacheShaPassword.Load(fmt.Sprintf("%s@%s", c.user, c.Conn.LocalAddr())) + cached, ok := c.serverConf.cacheShaPassword.Load(fmt.Sprintf("%s@%s", c.user, c.LocalAddr())) if ok { // Scramble validation if scrambleValidation(cached.([]byte), c.salt, clientAuthData) { diff --git a/server/auth_switch_response.go b/server/auth_switch_response.go index b11e1437f..9baccc03e 100644 --- a/server/auth_switch_response.go +++ b/server/auth_switch_response.go @@ -126,5 +126,5 @@ func (c *Conn) writeCachingSha2Cache() { crypt.Write(m1) m2 := crypt.Sum(nil) // caching_sha2_password will maintain an in-memory hash of `user`@`host` => SHA256(SHA256(PASSWORD)) - c.serverConf.cacheShaPassword.Store(fmt.Sprintf("%s@%s", c.user, c.Conn.LocalAddr()), m2) + c.serverConf.cacheShaPassword.Store(fmt.Sprintf("%s@%s", c.user, c.LocalAddr()), m2) }