fix: suppress unsupported Druid SQL parsing
This commit is contained in:
@@ -55,7 +55,9 @@ spring:
|
|||||||
# 慢SQL记录
|
# 慢SQL记录
|
||||||
log-slow-sql: true
|
log-slow-sql: true
|
||||||
slow-sql-millis: 1000
|
slow-sql-millis: 1000
|
||||||
merge-sql: true
|
# SQL Server THROW/MERGE/OUTPUT syntax is not understood by Druid 1.2.23.
|
||||||
|
# Keep statistics and slow-SQL logging, but skip SQL parameterization.
|
||||||
|
merge-sql: false
|
||||||
wall:
|
wall:
|
||||||
config:
|
config:
|
||||||
multi-statement-allow: true
|
multi-statement-allow: true
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.ruoyi.algorithm.shadow;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
|
import com.alibaba.druid.DbType;
|
||||||
|
import com.alibaba.druid.filter.stat.StatFilter;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
class ShadowInputMapperDruidCompatibilityTest {
|
||||||
|
|
||||||
|
private static final String MAPPER_RESOURCE = "mapper/algorithm/ShadowInputMapper.xml";
|
||||||
|
private static final Pattern MYBATIS_PARAMETER = Pattern.compile("#\\{[^}]+}");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void configuredDruidStatFilterSkipsUnsupportedParsingAndKeepsSlowSqlMonitoring() throws Exception {
|
||||||
|
String claimInstance = boundSql("claimInstance");
|
||||||
|
String upsertRuntimeMetric = boundSql("upsertRuntimeMetric");
|
||||||
|
StatFilter filter = configuredStatFilter();
|
||||||
|
|
||||||
|
assertAll(
|
||||||
|
() -> assertFalse(filter.isMergeSql()),
|
||||||
|
() -> assertEquals(1000L, filter.getSlowSqlMillis()),
|
||||||
|
() -> assertTrue(filter.isLogSlowSql()),
|
||||||
|
() -> assertDoesNotThrow(() -> assertEquals(
|
||||||
|
claimInstance, filter.mergeSql(claimInstance, DbType.sqlserver))),
|
||||||
|
() -> assertDoesNotThrow(() -> assertEquals(
|
||||||
|
upsertRuntimeMetric, filter.mergeSql(upsertRuntimeMetric, DbType.sqlserver))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StatFilter configuredStatFilter() throws Exception {
|
||||||
|
List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(
|
||||||
|
"application-druid", new ClassPathResource("application-druid.yml"));
|
||||||
|
StatFilter filter = new StatFilter();
|
||||||
|
filter.setMergeSql(property(sources, "spring.datasource.druid.filter.stat.merge-sql", Boolean.class));
|
||||||
|
filter.setLogSlowSql(property(sources, "spring.datasource.druid.filter.stat.log-slow-sql", Boolean.class));
|
||||||
|
filter.setSlowSqlMillis(property(sources, "spring.datasource.druid.filter.stat.slow-sql-millis", Integer.class));
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T property(List<PropertySource<?>> sources, String name, Class<T> type) {
|
||||||
|
return sources.stream()
|
||||||
|
.map(source -> source.getProperty(name))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst()
|
||||||
|
.map(type::cast)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("Configuration property not found: " + name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String boundSql(String statementId) throws Exception {
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||||
|
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||||
|
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||||
|
|
||||||
|
try (InputStream stream = Objects.requireNonNull(
|
||||||
|
Thread.currentThread().getContextClassLoader().getResourceAsStream(MAPPER_RESOURCE),
|
||||||
|
MAPPER_RESOURCE)) {
|
||||||
|
Document document = factory.newDocumentBuilder().parse(stream);
|
||||||
|
NodeList elements = document.getElementsByTagName("*");
|
||||||
|
for (int index = 0; index < elements.getLength(); index++) {
|
||||||
|
Element element = (Element) elements.item(index);
|
||||||
|
if (statementId.equals(element.getAttribute("id"))) {
|
||||||
|
return MYBATIS_PARAMETER.matcher(element.getTextContent()).replaceAll("?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Mapper statement not found: " + statementId);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user