Skip to content

Commit ab4d42e

Browse files
WangMinanzoemak
authored andcommitted
fix parser failed when binlog_row_value_options=partial_json (alibaba#5018)
* 修改json部分更新的问题 * 保证after-image的情况下位点回退完整
1 parent c3e50d4 commit ab4d42e

File tree

2 files changed

+57
-29
lines changed

2 files changed

+57
-29
lines changed

dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/JsonDiffConversion.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import java.nio.charset.Charset;
44
import java.util.ArrayList;
55
import java.util.List;
6+
import java.util.Objects;
67

78
import com.taobao.tddl.dbsync.binlog.JsonConversion.Json_Value;
89
import com.taobao.tddl.dbsync.binlog.JsonConversion.Json_enum_type;
910

1011
/**
1112
* 处理mysql8.0 parital json diff解析
12-
*
13+
*
1314
* @author agapple 2018年11月4日 下午3:53:46
1415
* @since 1.1.2
1516
*/
@@ -71,12 +72,20 @@ public static StringBuilder print_json_diff(LogBuffer buffer, long len, String c
7172

7273
buffer.forward((int) value_length);
7374
}
75+
76+
if (buffer.position - position >= len) {
77+
break;
78+
}
79+
}
80+
81+
if (buffer.position - position != len) {
82+
throw new IllegalArgumentException("reading json diff");
7483
}
7584

7685
// Print function names in reverse order.
7786
StringBuilder builder = new StringBuilder();
7887
for (int i = operation_names.size() - 1; i >= 0; i--) {
79-
if (i == 0 || operation_names.get(i - 1) != operation_names.get(i)) {
88+
if (i == 0 || !Objects.equals(operation_names.get(i - 1), operation_names.get(i))) {
8089
builder.append(operation_names.get(i)).append("(");
8190
}
8291
}
@@ -90,7 +99,7 @@ public static StringBuilder print_json_diff(LogBuffer buffer, long len, String c
9099

91100
// In case this vector is empty (a no-op), make an early return
92101
// after printing only the column name
93-
if (operation_names.size() == 0) {
102+
if (operation_names.isEmpty()) {
94103
return builder;
95104
}
96105

@@ -128,8 +137,13 @@ public static StringBuilder print_json_diff(LogBuffer buffer, long len, String c
128137
builder.append(jsonBuilder);
129138
}
130139

140+
if (buffer.position - position >= len) {
141+
builder.append(")");
142+
break;
143+
}
144+
131145
// Print closing parenthesis
132-
if (!buffer.hasRemaining() || operation_names.get(diff_i + 1) != operation_names.get(diff_i)) {
146+
if (!buffer.hasRemaining() || !Objects.equals(operation_names.get(diff_i + 1), operation_names.get(diff_i))) {
133147
builder.append(")");
134148
}
135149

@@ -139,6 +153,10 @@ public static StringBuilder print_json_diff(LogBuffer buffer, long len, String c
139153
diff_i++;
140154
}
141155

156+
if (buffer.position - position != len) {
157+
throw new IllegalArgumentException("reading json diff");
158+
}
159+
142160
return builder;
143161
}
144162

dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/event/RowsLogBuffer.java

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/**
2121
* Extracting JDBC type & value information from packed rows-buffer.
22-
*
22+
*
2323
* @see mysql-5.1.60/sql/log_event.cc - Rows_log_event::print_verbose_one_row
2424
* @author <a href="mailto:[email protected]">Changyuan.lh</a>
2525
* @version 1.0
@@ -70,7 +70,7 @@ public final boolean nextOneRow(BitSet columns) {
7070

7171
/**
7272
* Extracting next row from packed buffer.
73-
*
73+
*
7474
* @see mysql-5.1.60/sql/log_event.cc -
7575
* Rows_log_event::print_verbose_one_row
7676
*/
@@ -104,7 +104,7 @@ public final boolean nextOneRow(BitSet columns, boolean after) {
104104

105105
/**
106106
* Extracting next field value from packed buffer.
107-
*
107+
*
108108
* @see mysql-5.1.60/sql/log_event.cc -
109109
* Rows_log_event::print_verbose_one_row
110110
*/
@@ -114,7 +114,7 @@ public final Serializable nextValue(final String columName, final int columnInde
114114

115115
/**
116116
* Extracting next field value from packed buffer.
117-
*
117+
*
118118
* @see mysql-5.1.60/sql/log_event.cc -
119119
* Rows_log_event::print_verbose_one_row
120120
*/
@@ -277,7 +277,7 @@ static int mysqlToJavaType(int type, final int meta, boolean isBinary) {
277277

278278
/**
279279
* Extracting next field value from packed buffer.
280-
*
280+
*
281281
* @see mysql-5.1.60/sql/log_event.cc - log_event_print_value
282282
*/
283283
final Serializable fetchValue(String columnName, int columnIndex, int type, final int meta, boolean isBinary) {
@@ -1077,30 +1077,21 @@ final Serializable fetchValue(String columnName, int columnIndex, int type, fina
10771077
if (partialBits.get(1)) {
10781078
// print_json_diff
10791079
int position = buffer.position();
1080-
StringBuilder builder = JsonDiffConversion.print_json_diff(buffer,
1081-
len,
1082-
columnName,
1083-
columnIndex,
1084-
charset);
1085-
value = builder.toString();
1086-
buffer.position(position + len);
1087-
} else {
1088-
if (0 == len) {
1089-
// fixed issue #1 by lava, json column of zero length
1090-
// has no
1091-
// value, value parsing should be skipped
1092-
value = "";
1093-
} else {
1094-
int position = buffer.position();
1095-
Json_Value jsonValue = JsonConversion.parse_value(buffer.getUint8(),
1096-
buffer,
1097-
len - 1,
1080+
try {
1081+
StringBuilder builder = JsonDiffConversion.print_json_diff(buffer,
1082+
len,
1083+
columnName,
1084+
columnIndex,
10981085
charset);
1099-
StringBuilder builder = new StringBuilder();
1100-
jsonValue.toJsonString(builder, charset);
11011086
value = builder.toString();
11021087
buffer.position(position + len);
1088+
} catch (IllegalArgumentException e) {
1089+
buffer.position(position);
1090+
// print_json_diff failed, fallback to parse_value
1091+
parseJsonFromFullValue(len);
11031092
}
1093+
} else {
1094+
parseJsonFromFullValue(len);
11041095
}
11051096
javaType = Types.VARCHAR;
11061097
length = len;
@@ -1155,6 +1146,25 @@ final Serializable fetchValue(String columnName, int columnIndex, int type, fina
11551146
return value;
11561147
}
11571148

1149+
private void parseJsonFromFullValue(int len) {
1150+
if (0 == len) {
1151+
// fixed issue #1 by lava, json column of zero length
1152+
// has no
1153+
// value, value parsing should be skipped
1154+
value = "";
1155+
} else {
1156+
int position = buffer.position();
1157+
Json_Value jsonValue = JsonConversion.parse_value(buffer.getUint8(),
1158+
buffer,
1159+
len - 1,
1160+
charset);
1161+
StringBuilder builder = new StringBuilder();
1162+
jsonValue.toJsonString(builder, charset);
1163+
value = builder.toString();
1164+
buffer.position(position + len);
1165+
}
1166+
}
1167+
11581168
public final boolean isNull() {
11591169
return fNull;
11601170
}

0 commit comments

Comments
 (0)