Skip to content

Merge upstream#7

Draft
adamcrown wants to merge 236 commits into
masterfrom
merge-upstream
Draft

Merge upstream#7
adamcrown wants to merge 236 commits into
masterfrom
merge-upstream

Conversation

@adamcrown

Copy link
Copy Markdown
Member

This is a basic merge of upstream, but the merge conflicts were significant, so I had Claude handle the conflicts. I'm leaving this as a draft until I have a chance to review and test it.

Conflicts resolved (45 files):

  • Deleted 6 files upstream removed (failover package + server example)
  • Import paths: Changed all github.com/go-mysql-org/go-mysql → github.com/instructure/mc-go-mysql across the entire codebase
  • Replaced removed dependencies: DataDog/zstd → klauspost/compress/zstd, siddontang/go-log → log/slog, siddontang/go/ioutil2 → stdlib os, siddontang/go/hack → upstream's stmt/utils packages

Fork features preserved:

  • MasterInfoLoader interface + FsInfoLoader (file-based master info) + Redis loader support via InfoLoader config field
  • handleRetriableSync with syncErrorCh channel for the retry-on-failure logic and error propagation
  • proofOfSuccess flag that resets retry count on successful sync
  • GetTableForEvent method for column-count-aware table lookup

Upstream improvements incorporated:

  • Security-relevant dependency updates (edwards25519 1.2.0, klauspost/compress 1.18.6)
  • Structured logging with log/slog replacing old siddontang loggers
  • utils.Now() for testability, EventCacheCount/FillZeroLogPos config fields
  • New server authentication architecture, MySQL 8.4 semi-sync support, MariaDB GTID fixes
  • Various bug fixes for unsigned int decoding and binlog GTID parsing

dveeden and others added 30 commits May 7, 2023 09:49
Without the `USE...` in `TestExecuteMultiple` the test panics as the
result in `conn_test.go:108` is nil.

```
$ go test

----------------------------------------------------------------------
PANIC: conn_test.go:92: connTestSuite.TestExecuteMultiple

... Panic: runtime error: invalid memory address or nil pointer dereference (PC=0x438592)

/usr/lib/golang/src/runtime/panic.go:884
  in gopanic
/usr/lib/golang/src/runtime/panic.go:260
  in panicmem
/usr/lib/golang/src/runtime/signal_unix.go:837
  in sigpanic
conn_test.go:108
  in connTestSuite.TestExecuteMultiple.func1
conn.go:273
  in Conn.ExecuteMultiple
conn_test.go:101
  in connTestSuite.TestExecuteMultiple
/usr/lib/golang/src/reflect/value.go:370
  in Value.Call
/home/dvaneeden/go/pkg/mod/github.com/pingcap/check@v0.0.0-20190102082844-67f458068fc8/check.go:836
  in suiteRunner.forkTest.func1
/home/dvaneeden/go/pkg/mod/github.com/pingcap/check@v0.0.0-20190102082844-67f458068fc8/check.go:730
  in suiteRunner.forkCall.func1
/usr/lib/golang/src/runtime/asm_amd64.s:1598
  in goexit

----------------------------------------------------------------------
FAIL: conn_test.go:132: connTestSuite.TestExecuteSelectStreaming

conn_test.go:170:
    c.Assert(err, IsNil)
... value *mysql.MyError = &mysql.MyError{Code:0x416, Message:"No database selected", State:"3D000"} ("ERROR 1046 (3D000): No database selected")

----------------------------------------------------------------------
FAIL: conn_test.go:86: connTestSuite.TestFieldList

conn_test.go:88:
    c.Assert(err, IsNil)
... value *mysql.MyError = &mysql.MyError{Code:0x416, Message:"No database selected", State:"3D000"} ("ERROR 1046 (3D000): No database selected")

----------------------------------------------------------------------
FAIL: conn_test.go:38: connTestSuite.TearDownSuite

conn_test.go:43:
    s.testExecute_DropTable(c)
conn_test.go:83:
    c.Assert(err, IsNil)
... value *mysql.MyError = &mysql.MyError{Code:0x416, Message:"No database selected", State:"3D000"} ("ERROR 1046 (3D000): No database selected")

OOPS: 18 passed, 3 FAILED, 1 PANICKED
--- FAIL: Test (0.46s)
FAIL
exit status 1
FAIL	github.com/go-mysql-org/go-mysql/client	0.465s
```
Switch zstd library to allow build on arm64 and amd64
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.6 to 0.3.8.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](golang/text@v0.3.6...v0.3.8)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
client: wait connection producer exit in pool.Close()
…odules/golang.org/x/text-0.3.8

Bump golang.org/x/text from 0.3.6 to 0.3.8
client: fix ci
    client: add close method for client pool
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
dveeden and others added 29 commits February 18, 2026 09:15
…ql-org#1103)

Bumps [filippo.io/edwards25519](https://github.com/FiloSottile/edwards25519) from 1.1.0 to 1.1.1.
- [Commits](FiloSottile/edwards25519@v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: filippo.io/edwards25519
  dependency-version: 1.1.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: lance6716 <lance6716@gmail.com>
* driver: export Connector for structured sql.OpenDB

* driver: harden Connector option parsing

* export Conn

Signed-off-by: lance6716 <lance6716@gmail.com>

---------

Signed-off-by: lance6716 <lance6716@gmail.com>
* Extends TableColumn with attribute flags for DEFAULT_GENERATED and ON UPDATE

* schema: test DEFAULT_GENERATED and ON UPDATE flags

---------

Co-authored-by: lance6716 <lance6716@gmail.com>
* Adds OnTableNotFound() error handler to Canal

* Apply suggestions from code review

Co-authored-by: Daniël van Eeden <github@myname.nl>

---------

Co-authored-by: lance6716 <lance6716@gmail.com>
Co-authored-by: Daniël van Eeden <github@myname.nl>
* driver: improve RE matching case

Signed-off-by: lance6716 <lance6716@gmail.com>

* driver: address review comments

* driver: gofumpt

* driver: clarify compat DSN comment

---------

Signed-off-by: lance6716 <lance6716@gmail.com>
* Fix: incorrect offset in parseBinlogDumpGTID

* add: replication_test.go

* Update server/replication_test.go

---------

Co-authored-by: lance6716 <lance6716@gmail.com>
…-mysql-org#1117)

decodeValue now accepts an isUnsigned flag and returns the appropriate
unsigned Go type (uint8/uint16/uint32/uint64) for TINY/SHORT/INT24/LONG/
LONGLONG columns. decodeImage derives the flag per column from the
TableMapEvent UnsignedMap so values above the signed maximum are no
longer misrepresented as negative numbers.
…_TYPE_DECIMAL (go-mysql-org#1119)

* replication: fix IsNumericColumn to include MYSQL_TYPE_YEAR and MYSQL_TYPE_DECIMAL

MySQL's has_signedess_information_type() writes a SignednessBitmap bit for
MYSQL_TYPE_YEAR (and MYSQL_TYPE_DECIMAL) in TABLE_MAP_EVENT, but go-mysql's
IsNumericColumn() did not include these types. This caused UnsignedMap() to
silently skip the YEAR/DECIMAL bitmap bit, shifting every subsequent numeric
column to the wrong signedness value (off-by-one bitmap desync).

Fix: add MYSQL_TYPE_YEAR and MYSQL_TYPE_DECIMAL to IsNumericColumn() to match
MySQL's has_signedess_information_type() definition from
sql/field_common_properties.h.

Add TestUnsignedMapWithYearColumn to reproduce the exact scenario described in
the bug report (INT UNSIGNED → YEAR → INT UNSIGNED → DECIMAL UNSIGNED), and
update TestTableMapHelperMaps to reflect that the t_year column now correctly
appears in the UnsignedMap.

Fixes: YEAR column between numeric columns causes all following columns to
report wrong signedness in UnsignedMap().

Made-with: Cursor

* chore: remove comment

* fix: resolve review comments
…void duplicate domain id error (go-mysql-org#1122)

* fix: MariadbGTIDSet.AddSet() replace server entry on same domain to avoid duplicate domain id error

* refactor: remove explanatory comment from MariadbGTIDSet.AddSet() and TestMariaDBGTIDSetEqual()

* docs: add clarifying comments to MariadbGTIDSet and AddSet

---------

Co-authored-by: Sharath L P <sharathlp@microsoft.com>
…y per domain) (go-mysql-org#1124)

* refactor: flatten MariadbGTIDSet to map[uint32]*MariadbGTID (one entry per domain)

Fixes go-mysql-org#1123. MariaDB tracks one GTID position per domain_id. The nested
map[domainID]map[serverID]*MariadbGTID allowed multiple server entries per
domain, which is incorrect. Flatten to map[domainID]*MariadbGTID and use
forward() to handle server ID changes within a domain.

* docs: add comprehensive comments and tests for MariaDB GTID position semantics
…#1128)

SetReadDeadline unblocks ReadPacket so onStream notices ctx cancellation.
Some transports (notably SSH tunnels) refuse deadlines with an error, in
which case close the underlying connection to force ReadPacket to return.
Otherwise wg.Wait below parks forever when KILL also fails to reach server
(e.g. thread already reaped, "ERROR 1094 unknown thread id")

Co-authored-by: lance6716 <lance6716@gmail.com>
…on) (go-mysql-org#1125)

* mysql: Parsing MySQL GTIDs with tags (second alternative implementation)

Co-authored-by: lance6716 <lance6716@gmail.com>

* Update based on review

* Update based on review

* Fix formatting

* Move NewMysqlGTIDSet() next to type definition

* Fix FuzzTag_MarshalBinary

* Updates based on review

* Updates based on review

* mysql: preallocate slices in GTID set hot paths

Preallocate slice capacity where the final size is known, to avoid
incremental growslice reallocations and copy work in Clone, Encode,
String, Normalize, and DecodeMysqlGTIDSet. Also adds an Equal test
covering same-UUID/different-tag-count for full branch coverage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Simplify IntervalSlice.Equal() based on review

* mysql: make IntervalSlice.Contain robust to unsorted sub

The previous implementation walked s with a monotonic forward index,
silently relying on sub also being sorted. An unsorted sub produced
false negatives even when every interval was contained.

Switch to a per-sub[i] binary search over s. s still must be sorted
and normalized (the type's other operations enforce that invariant);
sub may now be in any order. O(m log n), no allocation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: lance6716 <lance6716@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Run go fix ./...

* Add modernice CI check
* Enable revive

* Use more idiomatic Go for builtin function overlap
* Update dependencies

* Run go fix ./...

* Remove Go 1.24 from CI

* Fix issues from linters
* CHANGELOG: Update for v1.15

* Update CHANGELOG.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Add note for breaking changes

* Update CHANGELOG.md

Co-authored-by: lance6716 <lance6716@gmail.com>

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: lance6716 <lance6716@gmail.com>
…#1138)

MySQL 8.0.26 renamed rpl_semi_sync_master_enabled to
rpl_semi_sync_source_enabled and the @rpl_semi_sync_slave session
variable to @rpl_semi_sync_replica, keeping the old names as aliases.
8.4.0 removed the old aliases entirely, so semi-sync replication failed
to negotiate against 8.4+ servers.

Match either spelling in SHOW VARIABLES and set both session user
variables, mirroring the approach already used for
@master_binlog_checksum/@source_binlog_checksum and the heartbeat
variables.

Refs go-mysql-org#866

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: lance6716 <lance6716@gmail.com>
* replication: add RenderJSONAsMySQLText flag for type-preserving JSON output

Existing JSON binary decoding goes through an intermediate Go value
(float64, shopspring/decimal, map[string]any, ...) and then json.Marshal,
which silently drops JSONB type tags:

  * JSONB_DOUBLE 1.0     -> float64(1.0) -> json.Marshal -> "1"
                            (re-parsed by MySQL as JSON INTEGER)
  * JSONB_OPAQUE/NEWDECIMAL 1.0
                         -> Go string "1.0" -> json.Marshal -> "\"1.0\""
                            (re-parsed by MySQL as JSON STRING)

Replaying either of those into a MySQL JSON column changes the stored
binary representation, which breaks CRC32-style row checksums in binlog
replication / online schema change tools.

This adds an opt-in BinlogSyncerConfig.RenderJSONAsMySQLText flag that
routes JSON values through a renderer (replication/json_mysql_text.go)
which emits MySQL-text-compatible JSON directly from the JSONB byte
stream, preserving each value's original type tag.

Mirrors the existing UseDecimal and UseFloatWithTrailingZero opt-in
flags: default behaviour is unchanged, callers feeding the decoded
string back into a MySQL JSON column opt in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* change implementation to use json_binary

* replication: satisfy modernize rangeint lint

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* replication: apply ignoreDecodeErr uniformly across both modes

Address PR review: drop the mysqlTextMode guard so IgnoreJSONDecodeError
behaves consistently for top-level short payloads regardless of the
rendering mode. Also fix a misleading DATE comment ("emitted" -> "omitted").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* incorporate reviewer feedback

* incorporate reviewer feedback

* replication: clarify test-helper doc and tidy test name

- Rename TestNewTransactionPayloadEvent_InheritsParent to drop the
  underscore, per review feedback.
- Reword the renderJSONAsMySQLText helper comment to be explicit that
  production code never calls it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* replication: drop underscores from new test function names

Per review feedback, rename all new tests in this PR to the no-underscore
TestSubjectVerbObject style used elsewhere in the package.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: replace interface{} with any (Go 1.18+)

* fix: apply gofumpt formatting to example_client_test.go
Resolves all merge conflicts while preserving fork-specific features:
- MCE-18894: Load binlog position from Redis (MasterInfoLoader interface)
- MCE-18519: Retriable sync with handleRetriableSync and syncErrorCh channel
- MCE-18274: FsInfoLoader for file-based master info persistence
- Custom column type handling (TYPE_TEXT, TYPE_BLOB)
- instructure/mc-go-mysql import paths throughout

Upstream changes incorporated:
- Security dependency updates (edwards25519, klauspost/compress, etc.)
- Replaced DataDog/zstd and siddontang/* with modern equivalents
- New utils.Now() for testability, slog-based structured logging
- New server authentication handler/provider architecture
- MySQL 8.4 semi-sync variable support, MariaDB GTID improvements
- EventCacheCount and FillZeroLogPos config options
- Removed failover package (upstream deleted)
- Various bug fixes: unsigned int decoding, binlog GTID parsing, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Jun 6, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 15 committers have signed the CLA.

✅ adamcrown
❌ ramnes
❌ olivierboucher
❌ dveeden
❌ dependabot[bot]
❌ lance6716
❌ zkramorev
❌ dbnski
❌ yanhao-pro
❌ vikaxsh
❌ triplefighter7619
❌ fansehep
❌ MD-Mushfiqur123
❌ morgo
❌ serprex
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.