From 209f09d5e9310b7c8b857f24690795cb0998dfc4 Mon Sep 17 00:00:00 2001 From: Alain Jobart Date: Mon, 1 May 2017 07:37:42 -0700 Subject: [PATCH] Stopping the parsing for unsupported json opaques. --- go/mysqlconn/replication/binlog_event_json.go | 20 +++++++--------- .../replication/binlog_event_json_test.go | 23 ++++++++++--------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/go/mysqlconn/replication/binlog_event_json.go b/go/mysqlconn/replication/binlog_event_json.go index f0a25422b67..8273091e700 100644 --- a/go/mysqlconn/replication/binlog_event_json.go +++ b/go/mysqlconn/replication/binlog_event_json.go @@ -72,7 +72,7 @@ func printJSONValue(typ byte, data []byte, toplevel bool, result *bytes.Buffer) case jsonTypeString: printJSONString(data, toplevel, result) case jsonTypeOpaque: - printJSONOpaque(data, toplevel, result) + return printJSONOpaque(data, toplevel, result) default: return fmt.Errorf("unknown object type in JSON: %v", typ) } @@ -345,17 +345,13 @@ func printJSONOpaque(data []byte, toplevel bool, result *bytes.Buffer) error { return printJSONDecimal(data[pos:pos+size], toplevel, result) } - // FIXME(alainjobart) this is broken for now. The lack of metadata - // makes the parsing fail. The MySQL source code is too obscure - // to make any sense of this. - val, pos, err := CellValue(data, pos, typ, 0, querypb.Type_INT8) - if err != nil { - return err - } - result.WriteString("CAST(") - val.EncodeSQL(result) - result.WriteString(" AS JSON)") - return nil + // Other types are encoded in somewhat weird ways. Since we + // have no metadata, it seems some types first provide the + // metadata, and then the values. But even that metadata is + // not straightforward (for instance, a bit field seems to + // have one byte as metadata, not two as would be expected). + // To be on the safer side, we just reject these cases for now. + return fmt.Errorf("opaque type %v is not supported yet, with data %v", typ, data[1:]) } func printJSONDate(data []byte, toplevel bool, result *bytes.Buffer) error { diff --git a/go/mysqlconn/replication/binlog_event_json_test.go b/go/mysqlconn/replication/binlog_event_json_test.go index 2c47e6220de..71bdfe8fe04 100644 --- a/go/mysqlconn/replication/binlog_event_json_test.go +++ b/go/mysqlconn/replication/binlog_event_json_test.go @@ -1,6 +1,9 @@ package replication -import "testing" +import ( + "fmt" + "testing" +) func TestJSON(t *testing.T) { testcases := []struct { @@ -99,23 +102,21 @@ func TestJSON(t *testing.T) { data: []byte{15, 246, 8, 13, 4, 135, 91, 205, 21, 4, 210}, expected: `CAST(CAST('123456789.1234' AS DECIMAL(13,4)) AS JSON)`, }, { - // opaque, bit field. - // FIXME(alainjobart) this is broken. It seems the '2' - // is the number of bytes (needed because there is no - // metadata), but I can't find how this works. - // So the parsing for now will produce an invalid string. + // opaque, bit field. Not yet implemented. data: []byte{15, 16, 2, 202, 254}, - expected: `CAST('' AS JSON)`, + expected: `ERROR: opaque type 16 is not supported yet, with data [2 202 254]`, }} for _, tcase := range testcases { r, err := printJSONData(tcase.data) + got := "" if err != nil { - t.Errorf("unexpected error for %v: %v", tcase.data, err) - continue + got = fmt.Sprintf("ERROR: %v", err) + } else { + got = string(r) } - if string(r) != tcase.expected { - t.Errorf("unexpected output for %v: got %v expected %v", tcase.data, string(r), tcase.expected) + if got != tcase.expected { + t.Errorf("unexpected output for %v: got %v expected %v", tcase.data, got, tcase.expected) } } }