From b28b811af79af504abd5dede1e4605843d887ec3 Mon Sep 17 00:00:00 2001 From: kezhenxu94 Date: Tue, 31 Mar 2020 00:04:17 +0800 Subject: [PATCH] [BugFix] Fix wrong H2 column type (#4593) MEDIUMTEXT in H2 is CLOB in JDBC type, and casting it to `String` causes `ClassCastException` --- .../server/core/storage/model/INewModel.java | 2 +- .../core/storage/model/StorageModels.java | 14 ++- .../plugin/jdbc/h2/dao/H2SQLExecutor.java | 86 +++++++++---------- .../plugin/jdbc/h2/dao/H2TableInstaller.java | 2 +- .../jdbc/mysql/MySQLTableInstaller.java | 9 ++ 5 files changed, 60 insertions(+), 53 deletions(-) diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/INewModel.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/INewModel.java index fab2194287..15df48ee9f 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/INewModel.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/INewModel.java @@ -30,5 +30,5 @@ public interface INewModel extends Service { * * @return the created new model */ - Model add(Class aClass, int scopeId, Storage storage, boolean record); + Model add(Class aClass, int scopeId, Storage storage, boolean record); } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java index 4d87142d5e..1632468381 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java @@ -43,7 +43,7 @@ public class StorageModels implements IModelManager, INewModel, IModelOverride { } @Override - public Model add(Class aClass, int scopeId, Storage storage, boolean record) { + public Model add(Class aClass, int scopeId, Storage storage, boolean record) { // Check this scope id is valid. DefaultScopeDefine.nameOf(scopeId); @@ -67,7 +67,7 @@ public class StorageModels implements IModelManager, INewModel, IModelOverride { return model; } - private void retrieval(Class clazz, + private void retrieval(Class clazz, String modelName, List modelColumns, List extraQueryIndices) { @@ -100,12 +100,10 @@ public class StorageModels implements IModelManager, INewModel, IModelOverride { Collections.addAll(indexDefinitions, field.getAnnotation(MultipleQueryUnifiedIndex.class).value()); } - indexDefinitions.forEach(indexDefinition -> { - extraQueryIndices.add(new ExtraQueryIndex( - column.columnName(), - indexDefinition.withColumns() - )); - }); + indexDefinitions.forEach(indexDefinition -> extraQueryIndices.add(new ExtraQueryIndex( + column.columnName(), + indexDefinition.withColumns() + ))); } } diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2SQLExecutor.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2SQLExecutor.java index 494f17a04b..bd26cd33bd 100644 --- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2SQLExecutor.java +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2SQLExecutor.java @@ -45,60 +45,60 @@ public class H2SQLExecutor { private static final Logger logger = LoggerFactory.getLogger(H2SQLExecutor.class); - protected List getByIDs(JDBCHikariCPClient h2Client, String modelName, String[] ids, - StorageBuilder storageBuilder) throws IOException { - - try (Connection connection = h2Client.getConnection()) { - /* - * Although H2 database or other database support createArrayOf and setArray operate. - * But Mysql 5.1.44 driver doesn't. - */ - String param = ArrayParamBuilder.build(ids); - - try (ResultSet rs = h2Client.executeQuery(connection, "SELECT * FROM " + modelName + " WHERE id in (" + param + ")")) { - List storageDataList = new ArrayList<>(); - StorageData storageData; - do { - storageData = toStorageData(rs, modelName, storageBuilder); - if (storageData != null) { - storageDataList.add(storageData); - } + protected List getByIDs(JDBCHikariCPClient h2Client, + String modelName, + String[] ids, + StorageBuilder storageBuilder) throws IOException { + /* + * Although H2 database or other database support createArrayOf and setArray operate. + * But Mysql 5.1.44 driver doesn't. + */ + String param = ArrayParamBuilder.build(ids); + + try (Connection connection = h2Client.getConnection(); + ResultSet rs = h2Client.executeQuery( + connection, "SELECT * FROM " + modelName + " WHERE id in (" + param + ")")) { + List storageDataList = new ArrayList<>(); + StorageData storageData; + do { + storageData = toStorageData(rs, modelName, storageBuilder); + if (storageData != null) { + storageDataList.add(storageData); } - while (storageData != null); - - return storageDataList; } + while (storageData != null); + + return storageDataList; } catch (SQLException | JDBCClientException e) { throw new IOException(e.getMessage(), e); } } - protected StorageData getByID(JDBCHikariCPClient h2Client, String modelName, String id, - StorageBuilder storageBuilder) throws IOException { - try (Connection connection = h2Client.getConnection()) { - try (ResultSet rs = h2Client.executeQuery(connection, "SELECT * FROM " + modelName + " WHERE id = ?", id)) { - return toStorageData(rs, modelName, storageBuilder); - } + protected StorageData getByID(JDBCHikariCPClient h2Client, String modelName, String id, + StorageBuilder storageBuilder) throws IOException { + try (Connection connection = h2Client.getConnection(); + ResultSet rs = h2Client.executeQuery(connection, "SELECT * FROM " + modelName + " WHERE id = ?", id)) { + return toStorageData(rs, modelName, storageBuilder); } catch (SQLException | JDBCClientException e) { throw new IOException(e.getMessage(), e); } } protected StorageData getByColumn(JDBCHikariCPClient h2Client, String modelName, String columnName, Object value, - StorageBuilder storageBuilder) throws IOException { - try (Connection connection = h2Client.getConnection()) { - try (ResultSet rs = h2Client.executeQuery(connection, "SELECT * FROM " + modelName + " WHERE " + columnName + " = ?", value)) { - return toStorageData(rs, modelName, storageBuilder); - } + StorageBuilder storageBuilder) throws IOException { + try (Connection connection = h2Client.getConnection(); + ResultSet rs = h2Client.executeQuery( + connection, "SELECT * FROM " + modelName + " WHERE " + columnName + " = ?", value)) { + return toStorageData(rs, modelName, storageBuilder); } catch (SQLException | JDBCClientException e) { throw new IOException(e.getMessage(), e); } } protected StorageData toStorageData(ResultSet rs, String modelName, - StorageBuilder storageBuilder) throws SQLException { + StorageBuilder storageBuilder) throws SQLException { if (rs.next()) { - Map data = new HashMap(); + Map data = new HashMap<>(); List columns = TableMetaInfo.get(modelName).getColumns(); for (ModelColumn column : columns) { data.put(column.getColumnName().getName(), rs.getObject(column.getColumnName().getStorageName())); @@ -109,11 +109,11 @@ public class H2SQLExecutor { } protected int getEntityIDByID(JDBCHikariCPClient h2Client, String entityColumnName, String modelName, String id) { - try (Connection connection = h2Client.getConnection()) { - try (ResultSet rs = h2Client.executeQuery(connection, "SELECT " + entityColumnName + " FROM " + modelName + " WHERE ID=?", id)) { - while (rs.next()) { - return rs.getInt(ServiceInstanceInventory.SEQUENCE); - } + try (Connection connection = h2Client.getConnection(); + ResultSet rs = h2Client.executeQuery( + connection, "SELECT " + entityColumnName + " FROM " + modelName + " WHERE ID=?", id)) { + if (rs.next()) { + return rs.getInt(ServiceInstanceInventory.SEQUENCE); } } catch (SQLException | JDBCClientException e) { logger.error(e.getMessage(), e); @@ -121,8 +121,8 @@ public class H2SQLExecutor { return Const.NONE; } - protected SQLExecutor getInsertExecutor(String modelName, StorageData metrics, - StorageBuilder storageBuilder) throws IOException { + protected SQLExecutor getInsertExecutor(String modelName, T metrics, + StorageBuilder storageBuilder) throws IOException { Map objectMap = storageBuilder.data2Map(metrics); SQLBuilder sqlBuilder = new SQLBuilder("INSERT INTO " + modelName + " VALUES"); @@ -149,8 +149,8 @@ public class H2SQLExecutor { return new SQLExecutor(sqlBuilder.toString(), param); } - protected SQLExecutor getUpdateExecutor(String modelName, StorageData metrics, - StorageBuilder storageBuilder) throws IOException { + protected SQLExecutor getUpdateExecutor(String modelName, T metrics, + StorageBuilder storageBuilder) throws IOException { Map objectMap = storageBuilder.data2Map(metrics); SQLBuilder sqlBuilder = new SQLBuilder("UPDATE " + modelName + " SET "); diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java index cb172ce872..07e5971d24 100644 --- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TableInstaller.java @@ -92,7 +92,7 @@ public class H2TableInstaller extends ModelInstaller { } else if (String.class.equals(type)) { return "VARCHAR(" + column.getLength() + ")"; } else if (IntKeyLongValueHashMap.class.equals(type)) { - return "MEDIUMTEXT"; + return "VARCHAR(20000)"; } else if (byte[].class.equals(type)) { return "MEDIUMTEXT"; } else { diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java index c44486334d..47fbb78931 100644 --- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/mysql/MySQLTableInstaller.java @@ -22,6 +22,7 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.oap.server.core.analysis.metrics.IntKeyLongValueHashMap; import org.apache.skywalking.oap.server.core.storage.StorageException; import org.apache.skywalking.oap.server.core.storage.model.ExtraQueryIndex; import org.apache.skywalking.oap.server.core.storage.model.Model; @@ -101,4 +102,12 @@ public class MySQLTableInstaller extends H2TableInstaller { createIndex(client, connection, model, tableIndexSQL); } } + + @Override + protected String getColumnType(final ModelColumn column) { + if (IntKeyLongValueHashMap.class.equals(column.getType())) { + return "MEDIUMTEXT"; + } + return super.getColumnType(column); + } } -- GitLab