兼容达梦

This commit is contained in:
guoshengxiong 2025-08-01 18:33:08 +08:00
parent e7eef4e308
commit 5d66ddffe9
11 changed files with 335 additions and 29 deletions

View File

@ -11,3 +11,23 @@
idea运行需要把内存修改大一点
![](asset/img.png)
# 兼容达梦连接mycat代理的达梦
## 创建函数:
CREATE OR REPLACE FUNCTION TO_DAYS(in_date DATE)
RETURN NUMBER
AS
BEGIN
RETURN TRUNC(in_date) - DATE '1970-01-01';
END;
## 修改server.xml配置
system标签下添加
<property name="sqlTranslate">true</property>
<property name="sqlTranslateType">dm</property>
<!-- 关键配置:移除反引号 -->
<property name="removeGraveAccent">1</property>
## 修改dm.ini配置
COMPATIBLE_MODE改成mysql的数字

View File

@ -14,18 +14,13 @@ import com.zhgd.annotation.DataScope;
import com.zhgd.jeecg.common.util.SpringContextUtils;
import com.zhgd.xmgl.constant.Cts;
import com.zhgd.xmgl.entity.dto.OperLogDataChange;
import com.zhgd.xmgl.entity.dto.OperLogInsertChange;
import com.zhgd.xmgl.security.util.SecurityUtils;
import com.zhgd.xmgl.util.EnvironmentUtil;
import com.zhgd.xmgl.util.LogMdcUtil;
import com.zhgd.xmgl.util.PrintColorUtil;
import com.zhgd.xmgl.util.ThreadLocalUtil;
import com.zhgd.xmgl.util.*;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
@ -41,7 +36,6 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
@ -196,14 +190,17 @@ public class DataScopeInterceptor extends JsqlParserSupport implements InnerInte
Method[] declaredMethods = clazz.getDeclaredMethods();
Optional<DataScope> dsOption = Arrays.stream(declaredMethods).filter(method -> method.getName().equals(methodName)).map(method -> method.getAnnotation(DataScope.class)).filter(Objects::nonNull).findFirst();
annotation = dsOption.orElseGet(() -> clazz.getAnnotation(DataScope.class));
if (findIgnoreDataScope(parameter, annotation) && isNotSqlTest()) {
return;
}
// if (findIgnoreDataScope(parameter, annotation) && isNotSqlTest()) {
// return;
// }
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
JSONObject jo = new JSONObject();
jo.put("ds", annotation);
jo.put("parameter", parameter);
mpBs.sql(this.parserSingle(mpBs.sql(), jo));
log.debug("原来sql{}",mpBs.sql());
//过滤器转换成达梦函数
String convertedSql = DamengUtil.convertMySQLFormatToDm(mpBs.sql());
mpBs.sql(this.parserSingle(convertedSql, jo));
} catch (Exception e) {
log.error(e.getMessage(), e);
}

View File

@ -337,6 +337,6 @@
from lifter_alarm la
where la.add_time >= #{queryStartTime}
and la.add_time <![CDATA[<=]]>
DATE_FORMAT(#{queryEndTime},'%Y-%m-%d 23:59:59')
CONCAT(DATE_FORMAT(#{queryEndTime},'%Y-%m-%d'), ' 23:59:59')
</select>
</mapper>

View File

@ -16,7 +16,7 @@
from dust_noise_data
where
<![CDATA[
upload_date < date_format(now(), '%Y-%m-%d 00:00:00')
upload_date < CONCAT(date_format(now(), '%Y-%m-%d'), ' 00:00:00')
]]>
</delete>
<insert id="insertDustNoiseHistoryData">
@ -46,7 +46,7 @@
from dust_noise_data
where
<![CDATA[
upload_date < date_format(now(), '%Y-%m-%d 00:00:00')
upload_date < CONCAT(date_format(now(), '%Y-%m-%d'), ' 00:00:00')
]]>
</insert>
<select id="selectDustNoiseData" resultType="com.zhgd.xmgl.modules.environment.entity.DustNoiseData"
@ -149,7 +149,7 @@
<if test="deviceId != null and deviceId != ''">
and device_id = #{deviceId}
</if>
and upload_date >= DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d 00:00:00')
and upload_date >= CONCAT(DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d'), ' 00:00:00')
group by time
</select>
</mapper>

View File

@ -6,7 +6,7 @@
select mepd.*,wi.worker_name driver_name,IFNULL(((case
when round((UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(heartbeat_time)) / 60) &lt;= 60
then 1
else 0 end)),0) online
else 0 end)),0) as online
from mechanical_equipment_position_dev mepd
left join worker_info wi on mepd.project_sn = wi.project_sn and wi.id=mepd.driver_id
${ew.customSqlSegment}

View File

@ -7,6 +7,7 @@
CONCAT(IFNULL(vpd.car_type, ''), IFNULL(ct.car_type_name, '')) carType,
CONCAT(IFNULL(vpd.driver, ''), IFNULL(wi.worker_name, '')) driver,
CONCAT(IFNULL(vpd.driver_telephone, ''), IFNULL(ci.driver_telephone, '')) driverTelephone
,vpd.project_sn
from vehicle_position_dev vpd
LEFT JOIN car_info ci ON ci.id = vpd.car_id
LEFT JOIN enterprise_info en ON en.id = ci.enterprise_id

View File

@ -111,8 +111,8 @@ public class VehiclePositionDevServiceImpl extends ServiceImpl<VehiclePositionDe
}
private QueryWrapper<VehiclePositionDev> getQueryWrapper(HashMap<String, Object> paramMap) {
String alias = "vpd.";
QueryWrapper<VehiclePositionDev> queryWrapper = QueryGenerator.initPageQueryWrapper(VehiclePositionDev.class, paramMap, alias);
String alias = "";
QueryWrapper<VehiclePositionDev> queryWrapper = QueryGenerator.initPageQueryWrapper(VehiclePositionDev.class, paramMap, false);
queryWrapper.orderByDesc(alias + RefUtil.fieldNameUlc(VehiclePositionDev::getId));
Integer online = MapUtils.getInteger(paramMap, "online");
if (online != null) {

View File

@ -146,7 +146,7 @@
and a.create_time >= CONCAT(DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -6 DAY), '%Y-%m-%d'), ' 00:00:00')
</if>
<if test="selectType == '3'.toString()">
and a.create_time >= DATE_FORMAT(NOW(), '%Y-%m-%d 00:00:00')
and a.create_time >= CONCAT(DATE_FORMAT(NOW(), '%Y-%m-%d'), ' 00:00:00')
</if>
<if test="selectType == '4'.toString()">
and a.create_time >= DATE_ADD(NOW(), INTERVAL -1 DAY)
@ -173,7 +173,7 @@
00:00:00'),1,0)),0) as past30AlarmNum,
ifnull(sum(if(a.create_time >= CONCAT(DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -6 DAY), '%Y-%m-%d'), '
00:00:00'),1,0)),0) as past7AlarmNum,
ifnull(sum(if(a.create_time >= DATE_FORMAT(NOW(), '%Y-%m-%d 00:00:00'),1,0)),0) as todayAlarmNum
ifnull(sum(if(a.create_time >= CONCAT(DATE_FORMAT(NOW(), '%Y-%m-%d'), ' 00:00:00'),1,0)),0) as todayAlarmNum
FROM ai_analyse_hard_ware_alarm_record a
where 1=1
and a.project_sn = #{projectSn}

View File

@ -1,6 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhgd.xmgl.modules.worker.mapper.WorkerAttendanceMapper">
<sql id="workerAttendanceSqlWithoutImageUrl">
a.id
,a.person_sn
,a.pass_type
,a.create_time
,a.project_sn
,a.dev_sn
,a.card_type
,a.attendance_type
,a.passageway_name
,a.attendance_status
,a.temperature
,a.is_statistics
,a.car_number
,a.health_code
,a.nucleic_acid_time
,a.nucleic_acid_result
,a.vaccinate_time
,a.vaccinate_state
</sql>
<select id="viewDayAttendanceList" resultType="com.zhgd.jeecg.common.mybatis.EntityMap">
SELECT a.attendance_status,
a.attendance_type,
@ -33,9 +53,10 @@
ORDER BY create_time DESC
</select>
<select id="selectWorkerAttendancePage" resultType="com.zhgd.jeecg.common.mybatis.EntityMap">
SELECT a.*,
SELECT
IF(a.image_url IS NOT NULL, a.image_url, b.id_card_big_photo_url) image_url,
code_state,
<include refid="workerAttendanceSqlWithoutImageUrl"></include>
,code_state,
b.worker_name,
b.id_card,
c.team_name,
@ -155,9 +176,10 @@
</select>
<select id="selectWorkerAttendanceNewestList" resultType="com.zhgd.jeecg.common.mybatis.EntityMap">
SELECT a.*,
SELECT
IF(a.image_url IS NOT NULL, a.image_url, b.id_card_big_photo_url) image_url,
b.worker_name,
<include refid="workerAttendanceSqlWithoutImageUrl"></include>
,b.worker_name,
b.id_card,
c.team_name,
d.department_name,
@ -311,9 +333,10 @@
<select id="selectWorkerAttendanceListByDev" resultType="com.zhgd.jeecg.common.mybatis.EntityMap"
parameterType="map">
SELECT a.*,
SELECT
IF(a.image_url IS NOT NULL, a.image_url, b.id_card_big_photo_url) image_url,
b.worker_name,
<include refid="workerAttendanceSqlWithoutImageUrl"></include>
,b.worker_name,
b.id_card,
c.team_name,
d.department_name,
@ -499,9 +522,10 @@
ORDER BY d.enterprise_id
</select>
<select id="selectWorkNewAttendanceList" resultType="com.zhgd.jeecg.common.mybatis.EntityMap">
SELECT a.*,
SELECT
IF(a.image_url IS NOT NULL, a.image_url, b.id_card_big_photo_url) image_url,
b.worker_name,
<include refid="workerAttendanceSqlWithoutImageUrl"></include>
,b.worker_name,
b.id_card,
c.team_name,
d.department_name,

View File

@ -777,7 +777,7 @@ public class WorkerInfoServiceImpl extends ServiceImpl<WorkerInfoMapper, WorkerI
private void setYesterday(Map<String, Object> map, PersonTypeAndEduStatisticsVo.AttendancePerson attendancePerson) {
map.put(Cts.QUERY_DATE, Cts.YESTERDAY);
Map<String, Object> ap = workerInfoMapper.selectAttendanceWorkerPersonTypeTotal(map);
attendancePerson.setTotalPersonRhbRatio(NumberUtils.rate(Double.valueOf(attendancePerson.getTotalPerson()), MapUtils.getDouble(ap, "totalPerson"), 2));
attendancePerson.setTotalPersonRhbRatio(NumberUtils.rate(Convert.toDouble(attendancePerson.getTotalPerson()), MapUtils.getDouble(ap, "totalPerson"), 2));
}
@Override

View File

@ -0,0 +1,264 @@
package com.zhgd.xmgl.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 达梦工具类
*/
public class DamengUtil {
/**
* 将MySQL的格式转换为达梦的格式
*
* @param sql
* @return
*/
public static String convertMySQLFormatToDm(String sql) {
sql = convertMySqlDateToDm(sql);
sql = convertDatediffToDaysBetween(sql);
sql = removeBackticks(sql);
sql = convertGroupConcatToWmConcat(sql);
sql = convertDoubleQuotesToSingle(sql);
sql = convertYearToDatePart(sql);
return sql;
}
/**
* 将MySQL的YEAR函数转换为SQL Server的DATEPART函数
*
* @param sql 原始SQL语句
* @return 转换后的SQL语句
*/
public static String convertYearToDatePart(String sql) {
// 匹配YEAR函数的正则表达式
// 匹配形式YEAR(date_column) YEAR(date_expression)
Pattern pattern = Pattern.compile(
"YEAR\\s*\\(\\s*([^\\)]+)\\s*\\)",
Pattern.CASE_INSENSITIVE
);
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String dateExpr = matcher.group(1).trim(); // 获取日期表达式
// 构建DATEPART函数
String datePart = String.format(
"DATEPART(YEAR, %s)",
dateExpr
);
matcher.appendReplacement(sb, datePart);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 将SQL中的双引号转换为单引号
* 特别处理DATE_FORMAT函数中的格式化字符串
*
* @param sql 原始SQL语句
* @return 转换后的SQL语句
*/
public static String convertDoubleQuotesToSingle(String sql) {
// 然后处理其他普通双引号
sql = sql.replace("\"", "'");
return sql;
}
/**
* 将MySQL的DATE_ADD/DATE_SUB函数转换为达梦兼容的DATEADD格式
*
* @param sql 原始SQL语句
* @return 转换后的SQL语句
*/
public static String convertMySqlDateToDm(String sql) {
// 匹配 DATE_ADD/DATE_SUB 函数的正则表达式不区分大小写
Pattern pattern = Pattern.compile(
"DATE_(ADD|SUB)\\s*\\(\\s*([^,]+)\\s*,\\s*INTERVAL\\s*(-?\\d+)\\s*(YEAR|MONTH|DAY|HOUR|MINUTE|SECOND)\\s*\\)",
Pattern.CASE_INSENSITIVE
);
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String function = matcher.group(1); // ADD or SUB
String dateExpr = matcher.group(2).trim(); // NOW() or other date expression
String num = matcher.group(3); // number
String unit = matcher.group(4).toUpperCase(); // time unit
// 处理SUB情况将数字取反
if ("SUB".equalsIgnoreCase(function)) {
num = "-" + num;
}
// 转换为达梦的DATEADD函数
String dmFunction = String.format("DATEADD(%s, %s, %s)",
unit, // 时间单位
num, // 数量
dateExpr // 日期表达式
);
matcher.appendReplacement(sb, dmFunction);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 将MySQL的GROUP_CONCAT函数转换为达梦兼容的WM_CONCAT格式
* 兼容处理DISTINCT和非DISTINCT两种情况
*
* @param sql 原始SQL语句
* @return 转换后的SQL语句
*/
public static String convertGroupConcatToWmConcat(String sql) {
// 匹配GROUP_CONCAT函数的正则表达式
// 匹配以下形式
// GROUP_CONCAT(DISTINCT column)
// GROUP_CONCAT(column)
// GROUP_CONCAT(column SEPARATOR ';')
// GROUP_CONCAT(DISTINCT column SEPARATOR ';')
Pattern pattern = Pattern.compile(
"GROUP_CONCAT\\s*\\(\\s*(DISTINCT\\s+)?([^\\)]+?)(?:\\s+SEPARATOR\\s+('[^']*'|\\S+))?\\s*\\)",
Pattern.CASE_INSENSITIVE
);
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String distinctPart = matcher.group(1); // 可能为"DISTINCT "或null
String columns = matcher.group(2).trim(); // 要连接的列表达式
String separator = matcher.group(3); // SEPARATOR部分可能为null
// 构建达梦的WM_CONCAT函数
StringBuilder dmFunction = new StringBuilder("WM_CONCAT(");
// 如果原始有DISTINCT需要特殊处理因为WM_CONCAT不支持DISTINCT
if (distinctPart != null && !distinctPart.trim().isEmpty()) {
// 方案1在外层使用DISTINCT
// dmFunction.append("DISTINCT ").append(columns);
// 方案2使用子查询去重更可靠
dmFunction.append("(SELECT WM_CONCAT(DISTINCT_VAL) FROM (SELECT DISTINCT ")
.append(columns).append(" AS DISTINCT_VAL))");
} else {
// 没有DISTINCT的直接转换
dmFunction.append(columns);
}
dmFunction.append(")");
// 处理SEPARATOR达梦默认用逗号分隔
if (separator != null && !separator.trim().isEmpty()) {
// 去掉引号如果SEPARATOR值有引号
String sepValue = separator.replaceAll("^'|'$", "");
// 使用REPLACE函数替换默认逗号
dmFunction.insert(0, "REPLACE(");
dmFunction.append(", ',', ").append("'").append(sepValue).append("'").append(")");
}
matcher.appendReplacement(sb, dmFunction.toString());
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 去除SQL中的反引号(`)
*
* @param sql 原始SQL语句
* @return 去除反引号后的SQL语句
*/
public static String removeBackticks(String sql) {
// 匹配被反引号包围的标识符
Pattern pattern = Pattern.compile("`([^`]+)`");
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 获取反引号中的内容
String identifier = matcher.group(1);
// 替换为不带反引号的内容
matcher.appendReplacement(sb, identifier);
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 将SQL中的DATEDIFF函数转换为DAYS_BETWEEN函数
*
* @param sql 原始SQL
* @return 转换后的SQL
*/
public static String convertDatediffToDaysBetween(String sql) {
// 匹配DATEDIFF函数的正则表达式
Pattern pattern = Pattern.compile(
"DATEDIFF\\s*\\(\\s*([^,]+)\\s*,\\s*([^)]+)\\s*\\)",
Pattern.CASE_INSENSITIVE
);
Matcher matcher = pattern.matcher(sql);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 获取两个日期参数
String date1 = matcher.group(1).trim();
String date2 = matcher.group(2).trim();
// 转换TO_CHAR为达梦兼容格式如果需要
date1 = convertToCharToDm(date1);
date2 = convertToCharToDm(date2);
// 替换为DAYS_BETWEEN函数
matcher.appendReplacement(sb, "DAYS_BETWEEN(" + date1 + ", " + date2 + ")");
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 转换TO_CHAR函数为达梦兼容格式
*/
private static String convertToCharToDm(String expr) {
if (expr.contains("TO_CHAR") || expr.contains("to_char")) {
return expr.replace("NOW()", "SYSDATE")
.replace("now()", "SYSDATE");
}
return expr;
}
/**
* 转换MySQL日期格式到达梦格式
*
* @param mysqlFormat MySQL格式字符串
* @return 达梦格式字符串
*/
private static String convertDateFormatPattern(String mysqlFormat) {
// 替换格式符号
String dmFormat = mysqlFormat
.replace("%Y", "YYYY")
.replace("%y", "YY")
.replace("%m", "MM")
.replace("%c", "MM") // %c在MySQL中是月份(1-12)
.replace("%d", "DD")
.replace("%e", "DD") // %e在MySQL中是月份中的天数(1-31)
.replace("%H", "HH24")
.replace("%h", "HH12")
.replace("%i", "MI")
.replace("%s", "SS")
.replace("%p", "AM");
return dmFormat;
}
}