From 9eb05a6ba40c25416e73a1381eef7ff31fcb443d Mon Sep 17 00:00:00 2001 From: Danish Sarwar Date: Wed, 29 Jul 2026 23:16:51 +0530 Subject: [PATCH] fix: size bigint unsigned as numeric(20,0); commit table migration tx MySQL BIGINT UNSIGNED columns propagate no source column length, so the redshift type defaulted to numeric(18,0). Values above 10^18-1 (e.g. the int64-max sentinel 9223372036854775807) fail COPY with "Overflow for NUMERIC(18,0)" and the loader retries the batch forever. Size such columns to numeric(20,0), which holds the full unsigned 64-bit range. Explicitly propagated lengths are respected. Also fix migrateTable: when redshiftGroup was set, it returned right after GrantSchemaAccess and skipped tx.Commit(), silently rolling back the whole table migration. The type widening above relies on this migration path committing. Co-Authored-By: Claude Fable 5 --- pkg/redshift/redshift.go | 7 ++++++ pkg/redshift/redshift_test.go | 33 ++++++++++++++++++++++++++++ pkg/redshiftloader/load_processor.go | 1 - 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/redshift/redshift.go b/pkg/redshift/redshift.go index d419acb6..ec28d4d9 100644 --- a/pkg/redshift/redshift.go +++ b/pkg/redshift/redshift.go @@ -1392,6 +1392,13 @@ func GetRedshiftDataType(sqlType, debeziumType, sourceColType, } } + // BIGINT UNSIGNED propagates no column length, and the default + // numeric(18,0) cannot hold its full range: COPY fails with + // "Overflow for NUMERIC(18,0)". Size it to 20 digits. + if sourceColType == "bigint unsigned" && sourceColLength == "" { + sourceColLength = "20" + } + return applyLength( RedshiftToMysqlCharacterRatio, redshiftType, diff --git a/pkg/redshift/redshift_test.go b/pkg/redshift/redshift_test.go index fa49665d..a8251706 100644 --- a/pkg/redshift/redshift_test.go +++ b/pkg/redshift/redshift_test.go @@ -337,6 +337,39 @@ func TestRedshiftDataTypeGet(t *testing.T) { expectedResult: "boolean", expectError: false, }, + { + name: "test29: BIGINT UNSIGNED without length covers full range", + sqlType: "mysql", + debeziumType: "string", + sourceColType: "BIGINT UNSIGNED", + sourceColLength: "", + sourceColScale: "", + columnMasked: false, + expectedResult: "numeric(20,0)", + expectError: false, + }, + { + name: "test30: BIGINT UNSIGNED with explicit length is respected", + sqlType: "mysql", + debeziumType: "string", + sourceColType: "BIGINT UNSIGNED", + sourceColLength: "22", + sourceColScale: "", + columnMasked: false, + expectedResult: "numeric(22,0)", + expectError: false, + }, + { + name: "test31: BIGINT UNSIGNED masked stays varchar", + sqlType: "mysql", + debeziumType: "string", + sourceColType: "BIGINT UNSIGNED", + sourceColLength: "", + sourceColScale: "", + columnMasked: true, + expectedResult: "character varying(50)", + expectError: false, + }, } for _, tc := range tests { diff --git a/pkg/redshiftloader/load_processor.go b/pkg/redshiftloader/load_processor.go index f419c033..c75d422d 100644 --- a/pkg/redshiftloader/load_processor.go +++ b/pkg/redshiftloader/load_processor.go @@ -577,7 +577,6 @@ func (b *loadProcessor) migrateTable( if err != nil { return err } - return err } err = tx.Commit()