From 67fe39ea93ac5e80edc3ba120d39aa24ec2f3276 Mon Sep 17 00:00:00 2001 From: immanuwell Date: Fri, 8 May 2026 14:34:45 +0400 Subject: [PATCH] fix: parse quoted PostgreSQL string arrays --- events-processor/utils/string.go | 58 ++++++++++++++++++++++----- events-processor/utils/string_test.go | 12 ++++++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/events-processor/utils/string.go b/events-processor/utils/string.go index 621e34684..9f495f1d3 100644 --- a/events-processor/utils/string.go +++ b/events-processor/utils/string.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "unicode" ) type StringArray []string @@ -52,22 +53,57 @@ func parsePostgresArray(s string) []string { return []string{} } - // Remove curly braces - s = strings.TrimPrefix(s, "{") - s = strings.TrimSuffix(s, "}") + if !strings.HasPrefix(s, "{") || !strings.HasSuffix(s, "}") { + return []string{strings.Trim(s, "\"")} + } + + s = strings.TrimSuffix(strings.TrimPrefix(s, "{"), "}") + result := make([]string, 0) + var current strings.Builder + inQuotes := false + escaped := false + quoted := false + tokenStarted := false - // Split by comma and clean up quotes - parts := strings.Split(s, ",") - result := make([]string, 0, len(parts)) + appendValue := func() { + value := current.String() + if !quoted { + value = strings.TrimSpace(value) + } + if quoted || value != "" { + result = append(result, value) + } + current.Reset() + quoted = false + tokenStarted = false + } - for _, part := range parts { - part = strings.TrimSpace(part) - part = strings.Trim(part, "\"") - if part != "" { - result = append(result, part) + for _, char := range s { + switch { + case escaped: + current.WriteRune(char) + escaped = false + tokenStarted = true + case char == '\\' && inQuotes: + escaped = true + case char == '"': + inQuotes = !inQuotes + quoted = true + tokenStarted = true + case char == ',' && !inQuotes: + appendValue() + case !inQuotes && quoted && unicode.IsSpace(char): + continue + case !inQuotes && !tokenStarted && unicode.IsSpace(char): + continue + default: + current.WriteRune(char) + tokenStarted = true } } + appendValue() + return result } diff --git a/events-processor/utils/string_test.go b/events-processor/utils/string_test.go index 352d92926..44fc3c509 100644 --- a/events-processor/utils/string_test.go +++ b/events-processor/utils/string_test.go @@ -102,6 +102,18 @@ func TestStringArray_Scan(t *testing.T) { expected: StringArray{"plain string"}, wantErr: false, }, + { + name: "postgres array with quoted comma", + input: `{"value,1","value2"}`, + expected: StringArray{"value,1", "value2"}, + wantErr: false, + }, + { + name: "postgres array with empty string", + input: `{"","value2"}`, + expected: StringArray{"", "value2"}, + wantErr: false, + }, } for _, tt := range tests {