Skip to content

Commit 9d577b7

Browse files
fix(shadowtable): bad sql grammer when table column's default value is a string type in MySQL (#2388)
* fix default value * fix structure compare * response to review --------- Co-authored-by: jingtian <[email protected]>
1 parent 760d710 commit 9d577b7

4 files changed

Lines changed: 44 additions & 0 deletions

File tree

server/odc-common/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,9 @@
171171
<groupId>com.auth0</groupId>
172172
<artifactId>java-jwt</artifactId>
173173
</dependency>
174+
<dependency>
175+
<groupId>com.oceanbase</groupId>
176+
<artifactId>db-browser</artifactId>
177+
</dependency>
174178
</dependencies>
175179
</project>

server/odc-common/src/main/java/com/oceanbase/odc/common/util/StringUtils.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,20 @@
1818
import java.net.URLDecoder;
1919
import java.net.URLEncoder;
2020
import java.nio.charset.StandardCharsets;
21+
import java.util.Locale;
2122
import java.util.Map;
2223
import java.util.Objects;
2324
import java.util.UUID;
2425
import java.util.regex.Matcher;
2526
import java.util.regex.Pattern;
2627

2728
import org.apache.commons.text.StringSubstitutor;
29+
import org.springframework.util.CollectionUtils;
2830

2931
import com.google.common.primitives.Chars;
32+
import com.oceanbase.tools.dbbrowser.model.DBTable;
33+
import com.oceanbase.tools.dbbrowser.model.DBTableColumn;
34+
import com.oceanbase.tools.dbbrowser.model.datatype.DataTypeUtil;
3035

3136
import lombok.NonNull;
3237

@@ -163,6 +168,31 @@ public static String unquoteSqlValue(final String str, final char wrapChar, fina
163168
return unescapeUseDouble(unwrap, escapeChars);
164169
}
165170

171+
public static void quoteColumnDefaultValuesForMySQL(DBTable table) {
172+
if (!CollectionUtils.isEmpty(table.getColumns())) {
173+
table.getColumns().forEach(column -> {
174+
String defaultValue = column.getDefaultValue();
175+
if (StringUtils.isNotEmpty(defaultValue)) {
176+
if (!isDefaultValueBuiltInFunction(column)) {
177+
column.setDefaultValue("'".concat(defaultValue.replace("'", "''")).concat("'"));
178+
}
179+
}
180+
});
181+
}
182+
}
183+
184+
/**
185+
* Check whether the data_default contain built in function. Any of the synonyms for
186+
* CURRENT_TIMESTAMP have the same meaning as CURRENT_TIMESTAMP. These are CURRENT_TIMESTAMP(),
187+
* NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, and LOCALTIMESTAMP().
188+
*/
189+
private static boolean isDefaultValueBuiltInFunction(DBTableColumn column) {
190+
return com.oceanbase.tools.dbbrowser.util.StringUtils.isEmpty(column.getDefaultValue())
191+
|| (!DataTypeUtil.isStringType(column.getTypeName())
192+
&& column.getDefaultValue().trim().toUpperCase(Locale.getDefault())
193+
.startsWith("CURRENT_TIMESTAMP"));
194+
}
195+
166196
public static String singleLine(final String str) {
167197
if (StringUtils.isEmpty(str)) {
168198
return str;

server/odc-service/src/main/java/com/oceanbase/odc/service/shadowtable/ShadowTableComparingTask.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ public Void call() {
104104
dbTableService.getTables(connectionSession, schemaName).entrySet().stream()
105105
.filter(entry -> allRealTableNames.contains(entry.getKey()))
106106
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
107+
if (connectionSession.getDialectType().isMysql()) {
108+
tableName2Tables.values().forEach(StringUtils::quoteColumnDefaultValuesForMySQL);
109+
}
110+
107111
} catch (Exception ex) {
108112
log.warn("fetch table meta information failed, ex={}", ex);
109113
comparingEntities.forEach(tableComparingEntity -> {

server/odc-service/src/main/java/com/oceanbase/odc/service/structurecompare/DefaultDBStructureComparator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import javax.sql.DataSource;
2626

2727
import com.oceanbase.odc.common.util.JdbcOperationsUtil;
28+
import com.oceanbase.odc.common.util.StringUtils;
2829
import com.oceanbase.odc.core.shared.constant.ConnectType;
2930
import com.oceanbase.odc.core.shared.constant.DialectType;
3031
import com.oceanbase.odc.service.db.browser.DBSchemaAccessors;
@@ -87,6 +88,11 @@ public List<DBObjectComparisonResult> compare(@NonNull DBStructureComparisonConf
8788
long startTimestamp = System.currentTimeMillis();
8889
Map<String, DBTable> srcTableName2Table = srcAccessor.getTables(srcConfig.getSchemaName(), null);
8990
Map<String, DBTable> tgtTableName2Table = tgtAccessor.getTables(tgtConfig.getSchemaName(), null);
91+
92+
if (srcConfig.getConnectType().getDialectType().isMysql()) {
93+
srcTableName2Table.values().forEach(StringUtils::quoteColumnDefaultValuesForMySQL);
94+
tgtTableName2Table.values().forEach(StringUtils::quoteColumnDefaultValuesForMySQL);
95+
}
9096
log.info(
9197
"DefaultDBStructureComparator build source and target schema tables success, time consuming={} seconds",
9298
(System.currentTimeMillis() - startTimestamp) / 1000);

0 commit comments

Comments
 (0)