COMMON_FUNCTIONS = defineCommonFunctionMap();
+
+ /**
+ *
+ * -----------------------定义公有函数-------------------------
+ * 在这里定义的是公有函数,没有必要必须在所有的数据库中存在,只保证在大部分数据库即可;
+ * 并且这里要将所有需要的函数全部定义上
+ *
+ * @return 公有函数
+ */
+ private static Map defineCommonFunctionMap(){
+ Map map = Maps.newHashMap();
+ // 需要获取到毫秒
+ map.put("NOW()", "CURRENT_TIMESTAMP(3)");
+
+ return map;
+ }
+
+ private Map initFunctionMap(){
+ Map map = Maps.newHashMap();
+ map.putAll(COMMON_FUNCTIONS);
+
+ // 使用自定义的函数进行重写
+ Map specifiedFunctions = specifiedFunctions();
+ if(specifiedFunctions!=null){
+ for (Map.Entry entry : specifiedFunctions.entrySet()){
+ if(COMMON_FUNCTIONS.containsKey(entry.getKey())){
+ map.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ return map;
+ }
+
+ /**
+ * -----------------------定义特定函数-------------------------
+ * 对于特定的数据库,如果一个函数,与公有函数定义的有所不同时,需要在这里定义
+ * @return 特定函数集
+ */
+ protected Map specifiedFunctions(){
+ return null;
+ }
+ public String getFunction(String functionName){
+ String func = this.functionMap.get(functionName);
+ if(Objs.isEmpty(func)){
+ throw new RuntimeException(StringTemplates.formatWithPlaceholder("function {} in {} database dialect is not supported", functionName, this.getName()));
+ }
+ return func;
+ }
+
+ public String getLimitSql(String sql, RowSelection rowSelection){
+ return this.delegate.getLimitSql(sql, rowSelection);
+ }
+
+ public String getLimitSql(String sql, boolean subQuery, boolean useLimitVariable, RowSelection rowSelection){
+ return this.delegate.getLimitSql(sql,useLimitVariable, subQuery, rowSelection);
+ }
+
+ public List rebuildParameters(List queryParams, RowSelection selection){
+ return rebuildParameters(false, true, queryParams, selection);
+ }
+
+ public List rebuildParameters(boolean subquery, boolean useLimitVariable, List queryParams, RowSelection selection){
+ return this.delegate.rebuildParameters(subquery,useLimitVariable, selection, queryParams);
+ }
+
+
+ public String wrapQuote(String identifier, Dialect.IdentifierCase identifierCase){
+ // 数据库表名、列名的大小写,由 dialect 内部实现
+ return this.delegate.getQuotedIdentifier(identifier, identifierCase);
+ }
+
+ public String unwrapQuote(String identifier){
+ return this.delegate.getUnquoteIdentifier(identifier);
+ }
+
+ public boolean isAutoCastEmptyStringToNull(){
+ return false;
+ }
+
+ /**
+ * 为了应对存入 "" 字符串时,被当作 null 处理的情况
+ */
+ public String genCastNullToDefaultExpression(String expressionOrIdentifier,@Nullable String defaultValue){
+ return expressionOrIdentifier;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/NacosDatabaseDialectManager.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/NacosDatabaseDialectManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..491aaf0b41fda1d466a716b0e9421ceb7545b6f1
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/NacosDatabaseDialectManager.java
@@ -0,0 +1,38 @@
+package com.jn.nacos.plugin.datasource;
+
+import com.alibaba.nacos.common.spi.NacosServiceLoader;
+import com.jn.langx.util.collection.Maps;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class NacosDatabaseDialectManager {
+
+ private Map dialectMap;
+
+ private NacosDatabaseDialectManager(){
+ init();
+ }
+ private void init(){
+ Collection dialects = NacosServiceLoader.load(NacosDatabaseDialect.class);
+ Map map = Maps.newHashMap();
+ for (NacosDatabaseDialect dialect : dialects){
+ map.put(dialect.getName(), dialect);
+ }
+ this.dialectMap = map;
+ }
+
+ public NacosDatabaseDialect getDialect(String databaseType){
+ NacosDatabaseDialect dialect = this.dialectMap.get(databaseType);
+ if(dialect==null){
+ dialect = new DefaultNacosDatabaseDialect(databaseType);
+ }
+ return dialect;
+ }
+
+ private static final NacosDatabaseDialectManager INSTANCE = new NacosDatabaseDialectManager();
+
+ public static NacosDatabaseDialectManager getInstance(){
+ return INSTANCE;
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/derby/DerbyDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/derby/DerbyDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e519eecb3d9153457f3d91c6014c1ef7fb4c4d5
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/derby/DerbyDatabaseDialect.java
@@ -0,0 +1,16 @@
+package com.jn.nacos.plugin.datasource.db.derby;
+
+import com.alibaba.nacos.plugin.datasource.enums.derby.TrustedDerbylFunctionEnum;
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class DerbyDatabaseDialect extends NacosDatabaseDialect {
+ public DerbyDatabaseDialect() {
+ super(DatabaseNames.DERBY);
+ }
+
+ @Override
+ public String getFunction(String functionName) {
+ return TrustedDerbylFunctionEnum.getFunctionByName(functionName);
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/gauss/OpenGaussDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/gauss/OpenGaussDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..23d2363ef5b7aa6545e093873463ad6e56d76e4c
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/gauss/OpenGaussDatabaseDialect.java
@@ -0,0 +1,20 @@
+package com.jn.nacos.plugin.datasource.db.gauss;
+
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class OpenGaussDatabaseDialect extends NacosDatabaseDialect {
+ public OpenGaussDatabaseDialect() {
+ super(DatabaseNames.OPENGAUSS);
+ }
+
+ @Override
+ public boolean isAutoCastEmptyStringToNull() {
+ return true;
+ }
+
+ @Override
+ public String genCastNullToDefaultExpression(String expressionOrIdentifier, String defaultValue) {
+ return " COALESCE("+expressionOrIdentifier+", '"+defaultValue+"') ";
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/kingbase/KingbaseDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/kingbase/KingbaseDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..79fe934e9850ec1de20209ea01c2f34f9c1a959b
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/kingbase/KingbaseDatabaseDialect.java
@@ -0,0 +1,15 @@
+package com.jn.nacos.plugin.datasource.db.kingbase;
+
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class KingbaseDatabaseDialect extends NacosDatabaseDialect {
+ public KingbaseDatabaseDialect() {
+ super(DatabaseNames.KINGBASE);
+ }
+
+ @Override
+ public String genCastNullToDefaultExpression(String expressionOrIdentifier, String defaultValue) {
+ return " NVL("+expressionOrIdentifier+", '"+defaultValue+"') ";
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/magicdata/MagicDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/magicdata/MagicDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..779a914265d11d99ddc7ef08d17f6f72c0077d66
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/magicdata/MagicDatabaseDialect.java
@@ -0,0 +1,20 @@
+package com.jn.nacos.plugin.datasource.db.magicdata;
+
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class MagicDatabaseDialect extends NacosDatabaseDialect {
+ public MagicDatabaseDialect() {
+ super(DatabaseNames.MAGICDATA);
+ }
+
+ @Override
+ public boolean isAutoCastEmptyStringToNull() {
+ return true;
+ }
+
+ @Override
+ public String genCastNullToDefaultExpression(String expressionOrIdentifier, String defaultValue) {
+ return " COALESCE("+expressionOrIdentifier+", '"+defaultValue+"') ";
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mssql/MssqlDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mssql/MssqlDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..84661d061710e1fa98b954e0a2b8fb810a1b199e
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mssql/MssqlDatabaseDialect.java
@@ -0,0 +1,20 @@
+package com.jn.nacos.plugin.datasource.db.mssql;
+
+import com.jn.langx.util.collection.Maps;
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+import java.util.Map;
+
+public class MssqlDatabaseDialect extends NacosDatabaseDialect {
+ public MssqlDatabaseDialect() {
+ super(DatabaseNames.MSSQL);
+ }
+
+ @Override
+ protected Map specifiedFunctions() {
+ Map map = Maps.newHashMap();
+ map.put("NOW()", "CURRENT_TIMESTAMP");
+ return map;
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mysql/MysqlDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mysql/MysqlDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..17cd3455ac06d8a08108a4537be9223cc9560fd1
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/mysql/MysqlDatabaseDialect.java
@@ -0,0 +1,17 @@
+package com.jn.nacos.plugin.datasource.db.mysql;
+
+import com.alibaba.nacos.plugin.datasource.enums.mysql.TrustedMysqlFunctionEnum;
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+
+public class MysqlDatabaseDialect extends NacosDatabaseDialect {
+ public MysqlDatabaseDialect() {
+ super(DatabaseNames.MYSQL);
+ }
+
+ @Override
+ public String getFunction(String functionName) {
+ return TrustedMysqlFunctionEnum.getFunctionByName(functionName);
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/oracle/OracleDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/oracle/OracleDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..6221c46fbb05c30d674c30c158ff6d7d6d095e50
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/oracle/OracleDatabaseDialect.java
@@ -0,0 +1,22 @@
+package com.jn.nacos.plugin.datasource.db.oracle;
+
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.IdentifierQuotedMode;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class OracleDatabaseDialect extends NacosDatabaseDialect {
+ public OracleDatabaseDialect(){
+ super(DatabaseNames.ORACLE);
+ this.identifierQuotedMode = IdentifierQuotedMode.UNQUOTED;
+ }
+
+ @Override
+ public boolean isAutoCastEmptyStringToNull() {
+ return true;
+ }
+
+ @Override
+ public String genCastNullToDefaultExpression(String expressionOrIdentifier, String defaultValue) {
+ return " NVL("+expressionOrIdentifier+", '"+defaultValue+"') ";
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/postgresql/PostgresDatabaseDialect.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/postgresql/PostgresDatabaseDialect.java
new file mode 100644
index 0000000000000000000000000000000000000000..21ae63ac50800988acc3a99d7beca7d0f80989ab
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/db/postgresql/PostgresDatabaseDialect.java
@@ -0,0 +1,16 @@
+package com.jn.nacos.plugin.datasource.db.postgresql;
+
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+
+public class PostgresDatabaseDialect extends NacosDatabaseDialect {
+ public PostgresDatabaseDialect() {
+ super(DatabaseNames.POSTGRESQL);
+ }
+
+ @Override
+ public boolean isAutoCastEmptyStringToNull() {
+ // 此测试结果基于 postgresql 15
+ return false;
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/BaseMapper.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/BaseMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d8645b5b70189d56f860145ee39318bbeb7e5f0
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/BaseMapper.java
@@ -0,0 +1,304 @@
+package com.jn.nacos.plugin.datasource.mapper;
+
+import com.alibaba.nacos.common.utils.NamespaceUtil;
+import com.alibaba.nacos.common.utils.VersionUtils;
+import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
+import com.alibaba.nacos.plugin.datasource.mapper.AbstractMapper;
+import com.alibaba.nacos.plugin.datasource.model.MapperContext;
+import com.alibaba.nacos.sys.env.EnvUtil;
+import com.jn.langx.util.Objs;
+import com.jn.langx.util.Preconditions;
+import com.jn.langx.util.Strings;
+import com.jn.langx.util.collection.Pipeline;
+import com.jn.langx.util.enums.Enums;
+import com.jn.nacos.plugin.datasource.DatabaseNames;
+import com.jn.nacos.plugin.datasource.IdentifierQuotedMode;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialect;
+import com.jn.nacos.plugin.datasource.NacosDatabaseDialectManager;
+import com.jn.sqlhelper.dialect.Dialect;
+import com.jn.sqlhelper.dialect.DialectRegistry;
+
+import java.util.List;
+
+public abstract class BaseMapper extends AbstractMapper {
+ private final String databaseName;
+ protected NacosDatabaseDialect dialect;
+ private IdentifierQuotedMode identifierQuotedModeInDDL;
+
+ protected BaseMapper() {
+ this.databaseName = getConfiguredDatabaseName();
+ Preconditions.checkTrue(!Objs.equals(DatabaseNames.UNSUPPORTED, this.databaseName), "database {} is unsupported", this.databaseName);
+ this.dialect = NacosDatabaseDialectManager.getInstance().getDialect(this.databaseName);
+ this.identifierQuotedModeInDDL = getConfiguredIdentifierQuotedMode();
+ }
+
+ /**
+ * 当使用的 create-schema.sql, create-tables.sql 不是插件提供的,需要指定该配置。
+ */
+ private IdentifierQuotedMode getConfiguredIdentifierQuotedMode(){
+ String modeString = EnvUtil.getProperty("db.sql.identifier.quoted.mode");
+ IdentifierQuotedMode mode = null;
+ if(Strings.isNotBlank(modeString)){
+ mode = Enums.ofName(IdentifierQuotedMode.class, modeString);
+ }
+ if(mode==null){
+ mode = this.dialect.getPluginProvidedDDLIdentifierQuotedMode();
+ }
+ if(mode==null){
+ mode = IdentifierQuotedMode.QUOTED;
+ }
+ return mode;
+ }
+
+ private String getConfiguredDatabaseName(){
+ String databaseName = EnvUtil.getProperty("spring.sql.init.platform");
+ if(Strings.isBlank(databaseName)){
+ // 这个是 nacos 中更早的配置 datasource 类型的方式
+ databaseName = EnvUtil.getProperty("spring.datasource.platform");
+ }
+ if(Strings.isBlank(databaseName)){
+ // 内嵌数据库 derby
+ if (EnvUtil.getStandaloneMode()){
+ databaseName = DatabaseNames.DERBY;
+ }
+ else{ // 默认数据库 MySQL
+ databaseName = DatabaseNames.MSSQL;
+ }
+ }else{
+ Dialect dialect = DialectRegistry.getInstance().gaussDialect(databaseName);
+ if(dialect==null){
+ databaseName = DatabaseNames.UNSUPPORTED;
+ }
+ }
+
+ // 因为 mysql 不支持 在子查询中 的limit,所以 不使用自定义的SQL,而使用官方的插件
+ if(Strings.isBlank(databaseName) || Objs.equals(DatabaseNames.DERBY, databaseName) || Objs.equals(DatabaseNames.MYSQL, databaseName)){
+ databaseName = DatabaseNames.UNDEFINED;
+ }
+ return databaseName;
+ }
+
+
+ @Override
+ public String getDataSource() {
+ return databaseName;
+ }
+
+ public NacosDatabaseDialect getDialect() {
+ return dialect;
+ }
+
+ public String getIdentifierInDb(String identifier){
+ String string;
+ switch (identifierQuotedModeInDDL){
+ case QUOTED:
+ // 这个要求 DDL文件中,所有的表名、列名使用小写形式
+ string = dialect.wrapQuote(identifier, Dialect.IdentifierCase.LOWER_CASE);
+ break;
+ case UNQUOTED:
+ // 去掉引号
+ string = dialect.unwrapQuote(identifier);
+ break;
+ case MIXED:
+ default:
+ // 按照数据库对未加引号的默认行为来处理
+ string = dialect.wrapQuote(identifier, null);
+ break;
+ }
+ return string;
+ }
+
+ @Override
+ public String getFunction(String functionName) {
+ return this.dialect.getFunction(functionName);
+ }
+
+ /***************************************************************************
+ * 接下来是重写的父类的函数
+ ***************************************************************************/
+
+ /**
+ *
+ * @param columns The columns
+ * @param where The where params
+ */
+ @Override
+ public String select(List columns, List where) {
+ StringBuilder sql = new StringBuilder();
+ String method = "SELECT ";
+ sql.append(method);
+ for (int i = 0; i < columns.size(); i++) {
+ sql.append(getIdentifierInDb(columns.get(i)));
+ if (i == columns.size() - 1) {
+ sql.append(" ");
+ } else {
+ sql.append(",");
+ }
+ }
+ sql.append("FROM ");
+ sql.append(getTableName());
+ sql.append(" ");
+
+ where = Pipeline.of(where).clearEmptys().asList();
+
+ if (Objs.isEmpty(where)) {
+ return sql.toString();
+ }
+
+ sql.append(genWhereClause(where));
+ return sql.toString();
+ }
+
+ @Override
+ public String insert(List columns) {
+ StringBuilder sql = new StringBuilder();
+ String method = "INSERT INTO ";
+ sql.append(method);
+ sql.append(getTableName());
+
+
+ int tenantIdColumnIndex = -1;
+ int size = columns.size();
+ sql.append("(");
+ for (int i = 0; i < size; i++) {
+ String columnName = getDialect().unwrapQuote(columns.get(i).split("@")[0]);
+ if(Strings.equalsIgnoreCase(columnName, "tenant_id")){
+ tenantIdColumnIndex = i;
+ }
+ sql.append(getIdentifierInDb(columnName));
+ if (i != columns.size() - 1) {
+ sql.append(", ");
+ }
+ }
+ sql.append(") ");
+
+ sql.append("VALUES");
+ sql.append("(");
+ for (int i = 0; i < size; i++) {
+ String[] parts = columns.get(i).split("@");
+ if (parts.length == 2) {
+ sql.append(getFunction(parts[1]));
+ } else {
+ if(i==tenantIdColumnIndex){
+ sql.append(getDialect().genCastNullToDefaultExpression("?", getDefaultTenantId()));
+ }else {
+ sql.append("?");
+ }
+ }
+ if (i != columns.size() - 1) {
+ sql.append(",");
+ }
+ }
+ sql.append(")");
+ return sql.toString();
+ }
+
+ @Override
+ public String update(List columns, List where) {
+ StringBuilder sql = new StringBuilder();
+ String method = "UPDATE ";
+ sql.append(method);
+ sql.append(getTableName()).append(" ").append("SET ");
+
+ for (int i = 0; i < columns.size(); i++) {
+ String[] parts = columns.get(i).split("@");
+ String column = getDialect().unwrapQuote(parts[0]);
+ if (parts.length == 2) {
+ sql.append(getIdentifierInDb(column)).append(" = ").append(getFunction(parts[1]));
+ } else {
+ sql.append(getIdentifierInDb(column)).append(" = ").append("?");
+ }
+ if (i != columns.size() - 1) {
+ sql.append(",");
+ }
+ }
+
+ where = Pipeline.of(where).clearEmptys().asList();
+ if (Objs.isEmpty(where)) {
+ return sql.toString();
+ }
+
+ sql.append(" ");
+ sql.append(genWhereClause(where));
+
+ return sql.toString();
+ }
+
+
+ @Override
+ public String delete(List where) {
+ StringBuilder sql = new StringBuilder();
+ String method = "DELETE ";
+ sql.append(method).append("FROM ").append(getTableName()).append(" ");
+ where = Pipeline.of(where).clearEmptys().asList();
+ if (Objs.isEmpty(where)) {
+ return sql.toString();
+ }
+ sql.append(genWhereClause(where));
+ return sql.toString();
+ }
+
+
+ @Override
+ public String count(List where) {
+ StringBuilder sql = new StringBuilder();
+ String method = "SELECT ";
+ sql.append(method);
+ sql.append("COUNT(*) FROM ");
+ sql.append(getTableName());
+ sql.append(" ");
+
+ where = Pipeline.of(where).clearEmptys().asList();
+ if (Objs.isEmpty(where)) {
+ return sql.toString();
+ }
+
+ sql.append(genWhereClause(where));
+ return sql.toString();
+ }
+
+ protected final String genWhereClause(List where) {
+ StringBuilder sql = new StringBuilder(" WHERE ");
+ for (int i = 0; i < where.size(); i++) {
+ String condition = getDialect().unwrapQuote(where.get(i));
+
+ if(Strings.equalsIgnoreCase(condition, "tenant_id") && getDialect().isAutoCastEmptyStringToNull()){
+ String castNullToDefaultExpression = getDialect().genCastNullToDefaultExpression("?", getDefaultTenantId());
+ sql.append(getIdentifierInDb(condition)).append(" = ").append(castNullToDefaultExpression);
+ }else{
+ sql.append(getIdentifierInDb(condition)).append(" = ").append("?");
+ }
+
+ if (i != where.size() - 1) {
+ sql.append(" AND ");
+ }
+ }
+ return sql.toString();
+ }
+
+ protected boolean hasEncryptedDataKeyColumn(){
+ String currentVersion = VersionUtils.version;
+ String[] segments = Strings.split(currentVersion, ".");
+ String nacosVersion = Strings.join(".", segments, 0, 3);
+ return VersionUtils.compareVersion(nacosVersion, "2.1.0")>=0;
+ }
+ private static final String NAMESPACE_PUBLIC_KEY = "public";
+ protected final String getDefaultTenantId(){
+ if(getDialect().isAutoCastEmptyStringToNull()){
+ return NAMESPACE_PUBLIC_KEY;
+ }
+ return NamespaceUtil.getNamespaceDefaultId();
+ }
+ protected final String useDefaultTenantIdIfBlank(String tenantId){
+ return Strings.useValueIfBlank(tenantId, getDefaultTenantId());
+ }
+
+ protected final void useDefaultTenantIdWithWhereParameter(MapperContext context){
+ Object tenantIdObj= context.getWhereParameter(FieldConstant.TENANT_ID);
+ String tenantId=null;
+ if(tenantIdObj!=null){
+ tenantId = (String)tenantIdObj;
+ }
+ context.putWhereParameter(FieldConstant.TENANT_ID, useDefaultTenantIdIfBlank(tenantId));
+ }
+}
diff --git a/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/CommonConfigInfoAggrMapper.java b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/CommonConfigInfoAggrMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..951d451df0743b963519d770c23e25eb12ab5815
--- /dev/null
+++ b/nacosplugin-datasource/src/main/java/com/jn/nacos/plugin/datasource/mapper/CommonConfigInfoAggrMapper.java
@@ -0,0 +1,53 @@
+package com.jn.nacos.plugin.datasource.mapper;
+
+import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
+import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper;
+import com.alibaba.nacos.plugin.datasource.model.MapperContext;
+import com.alibaba.nacos.plugin.datasource.model.MapperResult;
+import com.jn.langx.util.collection.Lists;
+import com.jn.sqlhelper.dialect.pagination.RowSelection;
+
+import java.util.List;
+
+public class CommonConfigInfoAggrMapper extends BaseMapper implements ConfigInfoAggrMapper {
+
+ @Override
+ public MapperResult findConfigInfoAggrByPageFetchRows(MapperContext context) {
+ useDefaultTenantIdWithWhereParameter(context);
+ final int startRow = context.getStartRow();
+ final int pageSize = context.getPageSize();
+ final String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID);
+ final String groupId = (String) context.getWhereParameter(FieldConstant.GROUP_ID);
+ final String tenantId = (String) context.getWhereParameter(FieldConstant.TENANT_ID);
+
+ RowSelection rowSelection = new RowSelection(startRow, pageSize);
+ List columns = Lists.newArrayList("data_id","group_id","tenant_id","datum_id","app_name","content");
+ List where = Lists.newArrayList("data_id", "group_id", "tenant_id");
+ String sql = select(columns, where) + " ORDER BY datum_id ";
+ List