chore: import upstream snapshot with attribution
This commit is contained in:
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.dialect;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
|
||||
/**
|
||||
* PostgreSQL database dialect.
|
||||
*
|
||||
* @author xiweng.yy
|
||||
*/
|
||||
public class PostgresqlDatabaseDialect extends AbstractDatabaseDialect {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLimitPageSqlWithMark(String sql) {
|
||||
return sql + " OFFSET ? LIMIT ? ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLimitPageSql(String sql, int pageNo, int pageSize) {
|
||||
return sql + " OFFSET " + getPagePrevNum(pageNo, pageSize) + " LIMIT " + pageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLimitPageSqlWithOffset(String sql, int startOffset, int pageSize) {
|
||||
return sql + " OFFSET " + startOffset + " LIMIT " + pageSize;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.enums.postgresql;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The TrustedSqlFunctionEnum enum class is used to enumerate and manage a list of trusted built-in SQL functions.
|
||||
* By using this enum, you can verify whether a given SQL function is part of the trusted functions list
|
||||
* to avoid potential SQL injection risks.
|
||||
*
|
||||
* @author caoyanan
|
||||
*/
|
||||
public enum TrustedPostgresqlFunctionEnum {
|
||||
|
||||
/**
|
||||
* NOW().
|
||||
*/
|
||||
NOW("NOW()", "NOW()");
|
||||
|
||||
private static final Map<String, TrustedPostgresqlFunctionEnum> LOOKUP_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (TrustedPostgresqlFunctionEnum entry : TrustedPostgresqlFunctionEnum.values()) {
|
||||
LOOKUP_MAP.put(entry.functionName, entry);
|
||||
}
|
||||
}
|
||||
|
||||
private final String functionName;
|
||||
|
||||
private final String function;
|
||||
|
||||
TrustedPostgresqlFunctionEnum(String functionName, String function) {
|
||||
this.functionName = functionName;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the function name.
|
||||
*
|
||||
* @param functionName function name
|
||||
* @return function
|
||||
*/
|
||||
public static String getFunctionByName(String functionName) {
|
||||
TrustedPostgresqlFunctionEnum entry = LOOKUP_MAP.get(functionName);
|
||||
if (entry != null) {
|
||||
return entry.function;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Invalid function name: %s", functionName));
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AbstractMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AiResourceMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.ext.WhereBuilder;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of {@link AiResourceMapper}.
|
||||
*
|
||||
* @author nacos
|
||||
*/
|
||||
public class AiResourceMapperByPostgresql extends AbstractMapper implements AiResourceMapper {
|
||||
|
||||
@Override
|
||||
public MapperResult findAiResourceFetchRows(MapperContext context) {
|
||||
WhereBuilder where = new WhereBuilder(
|
||||
"SELECT id,gmt_create,gmt_modified,name,type,c_desc,status,namespace_id,"
|
||||
+ "biz_tags,ext,c_from,version_info,meta_version,scope,owner,download_count "
|
||||
+ "FROM ai_resource");
|
||||
where.eq("namespace_id", context.getWhereParameter(FieldConstant.NAMESPACE_ID));
|
||||
|
||||
appendExtraQueryCondition(where, context);
|
||||
|
||||
MapperResult built = where.build();
|
||||
String sql = built.getSql() + resolveOrderByClause(context) + " LIMIT "
|
||||
+ context.getPageSize() + " OFFSET "
|
||||
+ context.getStartRow();
|
||||
return new MapperResult(sql, built.getParamList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AbstractMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AiResourceVersionMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.ext.WhereBuilder;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of {@link AiResourceVersionMapper}.
|
||||
*
|
||||
* @author nacos
|
||||
*/
|
||||
public class AiResourceVersionMapperByPostgresql extends AbstractMapper
|
||||
implements AiResourceVersionMapper {
|
||||
|
||||
@Override
|
||||
public MapperResult findAiResourceVersionFetchRows(MapperContext context) {
|
||||
WhereBuilder where = new WhereBuilder(
|
||||
"SELECT id,gmt_create,gmt_modified,type,author,name,c_desc,status,version,namespace_id,storage,publish_pipeline_info,download_count "
|
||||
+ "FROM ai_resource_version");
|
||||
where.eq("namespace_id", context.getWhereParameter(FieldConstant.NAMESPACE_ID));
|
||||
where.and().eq("name", context.getWhereParameter(FieldConstant.NAME));
|
||||
|
||||
Object type = context.getWhereParameter(FieldConstant.TYPE);
|
||||
if (type != null && StringUtils.isNotBlank(String.valueOf(type))) {
|
||||
where.and().eq("type", type);
|
||||
}
|
||||
Object status = context.getWhereParameter(FieldConstant.STATUS);
|
||||
if (status != null && StringUtils.isNotBlank(String.valueOf(status))) {
|
||||
where.and().eq("status", status);
|
||||
}
|
||||
Object version = context.getWhereParameter(FieldConstant.VERSION);
|
||||
if (version != null && StringUtils.isNotBlank(String.valueOf(version))) {
|
||||
where.and().eq("version", version);
|
||||
}
|
||||
|
||||
MapperResult built = where.build();
|
||||
String sql = built.getSql() + " ORDER BY gmt_modified DESC LIMIT " + context.getPageSize()
|
||||
+ " OFFSET "
|
||||
+ context.getStartRow();
|
||||
return new MapperResult(sql, built.getParamList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2024 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AbstractMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of ConfigInfoGrayMapper.
|
||||
*
|
||||
* @author WangzJi
|
||||
**/
|
||||
|
||||
public class ConfigInfoGrayMapperByPostgresql extends AbstractMapper
|
||||
implements ConfigInfoGrayMapper {
|
||||
|
||||
@Override
|
||||
public MapperResult findAllConfigInfoGrayForDumpAllFetchRows(MapperContext context) {
|
||||
String sql =
|
||||
" SELECT id,data_id,group_id,tenant_id,gray_name,gray_rule,app_name,content,md5,gmt_modified "
|
||||
+ " FROM config_info_gray ORDER BY id LIMIT " + context.getPageSize() + " OFFSET "
|
||||
+ context.getStartRow();
|
||||
return new MapperResult(sql, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.base.BaseConfigInfoMapper;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of ConfigInfoMapper.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
public class ConfigInfoMapperByPostgresql extends BaseConfigInfoMapper {
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ArrayUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.base.BaseConfigTagsRelationMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.ext.WhereBuilder;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of ConfigTagsRelationMapper.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
|
||||
public class ConfigTagsRelationMapperByPostgresql extends BaseConfigTagsRelationMapper {
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult findConfigInfoLike4PageFetchRows(MapperContext context) {
|
||||
final String tenant = (String) context.getWhereParameter(FieldConstant.TENANT_ID);
|
||||
final String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID);
|
||||
final String group = (String) context.getWhereParameter(FieldConstant.GROUP_ID);
|
||||
final String appName = (String) context.getWhereParameter(FieldConstant.APP_NAME);
|
||||
final String content = (String) context.getWhereParameter(FieldConstant.CONTENT);
|
||||
final String[] tagArr = (String[]) context.getWhereParameter(FieldConstant.TAG_ARR);
|
||||
final String[] types = (String[]) context.getWhereParameter(FieldConstant.TYPE);
|
||||
|
||||
// 构建内层查询:根据标签条件筛选配置
|
||||
WhereBuilder innerWhere = new WhereBuilder(
|
||||
"SELECT a.id,a.data_id,a.group_id,a.tenant_id,a.app_name,a.content,a.md5,a.encrypted_data_key,a.type,a.c_desc "
|
||||
+ "FROM config_info a ");
|
||||
innerWhere.like("a.tenant_id", tenant);
|
||||
if (StringUtils.isNotBlank(dataId)) {
|
||||
innerWhere.and().like("a.data_id", dataId);
|
||||
}
|
||||
if (StringUtils.isNotBlank(group)) {
|
||||
innerWhere.and().like("a.group_id", group);
|
||||
}
|
||||
if (StringUtils.isNotBlank(appName)) {
|
||||
innerWhere.and().eq("a.app_name", appName);
|
||||
}
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
innerWhere.and().like("a.content", content);
|
||||
}
|
||||
if (!ArrayUtils.isEmpty(tagArr)) {
|
||||
innerWhere.and().exists("SELECT 1 FROM config_tags_relation b WHERE ", sub -> {
|
||||
sub.eqColumn("b.id", "a.id").and().startParentheses();
|
||||
for (int i = 0; i < tagArr.length; i++) {
|
||||
if (i != 0) {
|
||||
sub.or();
|
||||
}
|
||||
sub.like("b.tag_name", tagArr[i]);
|
||||
}
|
||||
sub.endParentheses();
|
||||
});
|
||||
}
|
||||
if (!ArrayUtils.isEmpty(types)) {
|
||||
innerWhere.and().in("a.type", types);
|
||||
}
|
||||
|
||||
innerWhere.offset(context.getStartRow(), context.getPageSize());
|
||||
MapperResult innerResult = innerWhere.build();
|
||||
|
||||
// 构建外层查询:获取筛选出的配置的完整标签信息
|
||||
// 使用exists和标量子查询规避group by ...content..带来的大字段分组开销
|
||||
final String sql =
|
||||
"SELECT c.id,c.data_id,c.group_id,c.tenant_id,c.app_name,c.content,c.md5,c.encrypted_data_key,c.type,c.c_desc,"
|
||||
+ "(SELECT STRING_AGG(tag_name, ',') FROM config_tags_relation d WHERE d.id = c.id) as config_tags "
|
||||
+ "FROM (" + innerResult.getSql() + ") c ";
|
||||
return new MapperResult(sql, innerResult.getParamList());
|
||||
}
|
||||
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.base.BaseGroupCapacityMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The PostgreSQL implementation of GroupCapacityMapper.
|
||||
* Override methods to remove MySQL backticks around 'usage' field.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
public class GroupCapacityMapperByPostgresql extends BaseGroupCapacityMapper {
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult select(MapperContext context) {
|
||||
String sql =
|
||||
"SELECT id, quota, usage, max_size, max_aggr_count, max_aggr_size, group_id FROM group_capacity "
|
||||
+ "WHERE group_id = ?";
|
||||
return new MapperResult(sql,
|
||||
Collections.singletonList(context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult insertIntoSelect(MapperContext context) {
|
||||
List<Object> paramList = new ArrayList<>();
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GROUP_ID));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.QUOTA));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_COUNT));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_CREATE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_MODIFIED));
|
||||
|
||||
String sql =
|
||||
"INSERT INTO group_capacity (group_id, quota, usage, max_size, max_aggr_count, max_aggr_size,"
|
||||
+ " max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info";
|
||||
return new MapperResult(sql, paramList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult insertIntoSelectByWhere(MapperContext context) {
|
||||
final String sql =
|
||||
"INSERT INTO group_capacity (group_id, quota, usage, max_size, max_aggr_count, max_aggr_size,"
|
||||
+ " max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info WHERE group_id=? AND tenant_id = '"
|
||||
+ NamespaceUtil.getNamespaceDefaultId() + "'";
|
||||
List<Object> paramList = new ArrayList<>();
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GROUP_ID));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.QUOTA));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_COUNT));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_CREATE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_MODIFIED));
|
||||
|
||||
paramList.add(context.getWhereParameter(FieldConstant.GROUP_ID));
|
||||
|
||||
return new MapperResult(sql, paramList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsageByWhereQuotaEqualZero(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? WHERE group_id = ? AND usage < ? AND quota = 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID),
|
||||
context.getWhereParameter(FieldConstant.USAGE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsageByWhereQuotaNotEqualZero(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? WHERE group_id = ? AND usage < quota AND quota != 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsageByWhere(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? WHERE group_id = ?",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult decrementUsageByWhere(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = usage - 1, gmt_modified = ? WHERE group_id = ? AND usage > 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult updateUsage(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = (SELECT count(*) FROM config_info), gmt_modified = ? WHERE group_id = ?",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult updateUsageByWhere(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE group_capacity SET usage = (SELECT count(*) FROM config_info WHERE group_id=? AND tenant_id = '"
|
||||
+ NamespaceUtil.getNamespaceDefaultId() + "'),"
|
||||
+ " gmt_modified = ? WHERE group_id= ?",
|
||||
CollectionUtils.list(context.getWhereParameter(FieldConstant.GROUP_ID),
|
||||
context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID)));
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.enums.postgresql.TrustedPostgresqlFunctionEnum;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AbstractMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.HistoryConfigInfoMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of HistoryConfigInfoMapper.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
public class HistoryConfigInfoMapperByPostgresql extends AbstractMapper
|
||||
implements HistoryConfigInfoMapper {
|
||||
|
||||
@Override
|
||||
public MapperResult removeConfigHistory(MapperContext context) {
|
||||
String sql =
|
||||
"WITH temp_table as (SELECT id FROM his_config_info WHERE gmt_modified < ? LIMIT ? ) "
|
||||
+ "DELETE FROM his_config_info WHERE id in (SELECT id FROM temp_table) ";
|
||||
return new MapperResult(sql,
|
||||
CollectionUtils.list(context.getWhereParameter(FieldConstant.START_TIME),
|
||||
context.getWhereParameter(FieldConstant.LIMIT_SIZE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult pageFindConfigHistoryFetchRows(MapperContext context) {
|
||||
String sql =
|
||||
"SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,ext_info,publish_type,gray_name,gmt_create,gmt_modified "
|
||||
+ "FROM his_config_info WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY nid DESC LIMIT "
|
||||
+ context.getPageSize() + " OFFSET " + context.getStartRow();
|
||||
return new MapperResult(sql,
|
||||
CollectionUtils.list(context.getWhereParameter(FieldConstant.DATA_ID),
|
||||
context.getWhereParameter(FieldConstant.GROUP_ID),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFunction(String functionName) {
|
||||
return TrustedPostgresqlFunctionEnum.getFunctionByName(functionName);
|
||||
}
|
||||
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.base.BaseTenantCapacityMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The PostgreSQL implementation of TenantCapacityMapper.
|
||||
* Override methods to remove MySQL backticks around 'usage' field.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
public class TenantCapacityMapperByPostgresql extends BaseTenantCapacityMapper {
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult select(MapperContext context) {
|
||||
String sql =
|
||||
"SELECT id, quota, usage, max_size, max_aggr_count, max_aggr_size, tenant_id FROM tenant_capacity "
|
||||
+ "WHERE tenant_id = ?";
|
||||
return new MapperResult(sql,
|
||||
Collections.singletonList(context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsageWithDefaultQuotaLimit(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = ? AND usage <"
|
||||
+ " ? AND quota = 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID),
|
||||
context.getWhereParameter(FieldConstant.USAGE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsageWithQuotaLimit(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = ? AND usage < "
|
||||
+ "quota AND quota != 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult incrementUsage(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? WHERE tenant_id = ?",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult decrementUsage(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE tenant_capacity SET usage = usage - 1, gmt_modified = ? WHERE tenant_id = ? AND usage > 0",
|
||||
CollectionUtils.list(context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult correctUsage(MapperContext context) {
|
||||
return new MapperResult(
|
||||
"UPDATE tenant_capacity SET usage = (SELECT count(*) FROM config_info WHERE tenant_id = ?), "
|
||||
+ "gmt_modified = ? WHERE tenant_id = ?",
|
||||
CollectionUtils.list(context.getWhereParameter(FieldConstant.TENANT_ID),
|
||||
context.getUpdateParameter(FieldConstant.GMT_MODIFIED),
|
||||
context.getWhereParameter(FieldConstant.TENANT_ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperResult insertTenantCapacity(MapperContext context) {
|
||||
List<Object> paramList = new ArrayList<>();
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.TENANT_ID));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.QUOTA));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_COUNT));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.MAX_AGGR_SIZE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_CREATE));
|
||||
paramList.add(context.getUpdateParameter(FieldConstant.GMT_MODIFIED));
|
||||
paramList.add(context.getWhereParameter(FieldConstant.TENANT_ID));
|
||||
|
||||
return new MapperResult(
|
||||
"INSERT INTO tenant_capacity (tenant_id, quota, usage, max_size, max_aggr_count, max_aggr_size, "
|
||||
+ "max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info WHERE tenant_id=?",
|
||||
paramList);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.base.BaseTenantInfoMapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The postgresql implementation of TenantInfoMapper.
|
||||
* Override insert/update to convert epoch-millis (bigint) to PostgreSQL timestamp
|
||||
* via {@code TO_TIMESTAMP(? / 1000.0)}.
|
||||
*
|
||||
* @author Long Yu
|
||||
**/
|
||||
public class TenantInfoMapperByPostgresql extends BaseTenantInfoMapper {
|
||||
|
||||
private static final String COLUMN_SEPARATOR = "@";
|
||||
|
||||
@Override
|
||||
public String getDataSource() {
|
||||
return DatabaseTypeConstant.POSTGRESQL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String insert(List<String> columns) {
|
||||
StringJoiner columnJoiner = new StringJoiner(", ", "(", ")");
|
||||
StringJoiner valueJoiner = new StringJoiner(",", "(", ")");
|
||||
|
||||
for (String col : columns) {
|
||||
String[] parts = col.split(COLUMN_SEPARATOR, 2);
|
||||
String colName = parts[0];
|
||||
columnJoiner.add(colName);
|
||||
if (parts.length > 1) {
|
||||
valueJoiner.add(getFunction(parts[1]));
|
||||
} else if (isTimestampColumn(colName)) {
|
||||
valueJoiner.add("TO_TIMESTAMP(? / 1000.0)");
|
||||
} else {
|
||||
valueJoiner.add("?");
|
||||
}
|
||||
}
|
||||
|
||||
return "INSERT INTO " + getTableName() + columnJoiner + " VALUES" + valueJoiner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String update(List<String> columns, List<String> where) {
|
||||
StringJoiner setJoiner = new StringJoiner(",");
|
||||
for (String col : columns) {
|
||||
String[] parts = col.split(COLUMN_SEPARATOR, 2);
|
||||
String colName = parts[0];
|
||||
String value;
|
||||
if (parts.length > 1) {
|
||||
value = getFunction(parts[1]);
|
||||
} else if (isTimestampColumn(colName)) {
|
||||
value = "TO_TIMESTAMP(? / 1000.0)";
|
||||
} else {
|
||||
value = "?";
|
||||
}
|
||||
setJoiner.add(colName + " = " + value);
|
||||
}
|
||||
|
||||
StringBuilder sql =
|
||||
new StringBuilder("UPDATE ").append(getTableName()).append(" SET ").append(setJoiner);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(where)) {
|
||||
sql.append(" WHERE ");
|
||||
sql.append(
|
||||
where.stream().map(str -> (str + " = ?")).collect(Collectors.joining(" AND ")));
|
||||
}
|
||||
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
private boolean isTimestampColumn(String columnName) {
|
||||
return "gmt_create".equals(columnName) || "gmt_modified".equals(columnName);
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Optional: grant read/write on existing Nacos tables to application role `nacos` only.
|
||||
*
|
||||
* When to use:
|
||||
* Load pg-schema.sql as a DBA/superuser (tables then belong to that role). Create the app user:
|
||||
* CREATE USER nacos WITH PASSWORD 'your-password';
|
||||
* Then run this script while connected to the Nacos database as the same role that owns the tables
|
||||
* (often superuser), so privileges apply to all current objects.
|
||||
*
|
||||
* What you get:
|
||||
* USAGE on public schema, SELECT/INSERT/UPDATE/DELETE on all tables, USAGE+SELECT on sequences
|
||||
* (covers bigserial / identity). No CREATE/DROP on schema, no superuser.
|
||||
*
|
||||
* CONNECT: use `psql -d your_nacos_db` so the session can open the DB, or from another database run:
|
||||
* GRANT CONNECT ON DATABASE your_nacos_db TO nacos;
|
||||
*/
|
||||
|
||||
GRANT USAGE ON SCHEMA public TO nacos;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO nacos;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO nacos;
|
||||
|
||||
-- Objects created later by the same owner (e.g. future migrations run as superuser):
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO nacos;
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
||||
GRANT USAGE, SELECT ON SEQUENCES TO nacos;
|
||||
+556
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for config_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "config_info";
|
||||
CREATE TABLE "config_info" (
|
||||
"id" bigserial NOT NULL,
|
||||
"data_id" varchar(255) NOT NULL,
|
||||
"group_id" varchar(255) ,
|
||||
"content" text NOT NULL,
|
||||
"md5" varchar(32) ,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"src_user" text ,
|
||||
"src_ip" varchar(20) ,
|
||||
"app_name" varchar(128) ,
|
||||
"tenant_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"c_desc" varchar(256) ,
|
||||
"c_use" varchar(64) ,
|
||||
"effect" varchar(64) ,
|
||||
"type" varchar(64) ,
|
||||
"c_schema" text ,
|
||||
"encrypted_data_key" text NOT NULL
|
||||
)
|
||||
;
|
||||
|
||||
COMMENT ON COLUMN "config_info"."id" IS 'id';
|
||||
COMMENT ON COLUMN "config_info"."data_id" IS 'data_id';
|
||||
COMMENT ON COLUMN "config_info"."content" IS 'content';
|
||||
COMMENT ON COLUMN "config_info"."md5" IS 'md5';
|
||||
COMMENT ON COLUMN "config_info"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "config_info"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON COLUMN "config_info"."src_user" IS 'source user';
|
||||
COMMENT ON COLUMN "config_info"."src_ip" IS 'source ip';
|
||||
COMMENT ON COLUMN "config_info"."tenant_id" IS '租户字段';
|
||||
COMMENT ON COLUMN "config_info"."encrypted_data_key" IS '秘钥';
|
||||
COMMENT ON TABLE "config_info" IS 'config_info';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for config_info_gray
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "config_info_gray";
|
||||
CREATE TABLE "config_info_gray" (
|
||||
"id" bigserial NOT NULL,
|
||||
"data_id" varchar(255) NOT NULL,
|
||||
"group_id" varchar(128) NOT NULL,
|
||||
"content" text NOT NULL,
|
||||
"md5" varchar(32),
|
||||
"src_user" text,
|
||||
"src_ip" varchar(100),
|
||||
"gmt_create" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"app_name" varchar(128),
|
||||
"tenant_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"gray_name" varchar(128) NOT NULL,
|
||||
"gray_rule" text NOT NULL,
|
||||
"encrypted_data_key" varchar(256) NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN "config_info_gray"."id" IS 'id';
|
||||
COMMENT ON COLUMN "config_info_gray"."data_id" IS 'data_id';
|
||||
COMMENT ON COLUMN "config_info_gray"."group_id" IS 'group_id';
|
||||
COMMENT ON COLUMN "config_info_gray"."content" IS 'content';
|
||||
COMMENT ON COLUMN "config_info_gray"."md5" IS 'md5';
|
||||
COMMENT ON COLUMN "config_info_gray"."src_user" IS 'source user';
|
||||
COMMENT ON COLUMN "config_info_gray"."src_ip" IS 'source ip';
|
||||
COMMENT ON COLUMN "config_info_gray"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "config_info_gray"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON COLUMN "config_info_gray"."app_name" IS 'app_name';
|
||||
COMMENT ON COLUMN "config_info_gray"."tenant_id" IS '租户字段';
|
||||
COMMENT ON COLUMN "config_info_gray"."gray_name" IS '灰度名称';
|
||||
COMMENT ON COLUMN "config_info_gray"."gray_rule" IS '灰度规则';
|
||||
COMMENT ON COLUMN "config_info_gray"."encrypted_data_key" IS '秘钥';
|
||||
COMMENT ON TABLE "config_info_gray" IS 'config_info_gray';
|
||||
|
||||
-- 创建索引
|
||||
CREATE UNIQUE INDEX "uk_configinfogray_datagrouptenantgray" ON "config_info_gray" USING btree ("data_id", "group_id", "tenant_id", "gray_name");
|
||||
CREATE INDEX "idx_dataid_gmt_modified_gray" ON "config_info_gray" USING btree ("data_id", "gmt_modified");
|
||||
CREATE INDEX "idx_gmt_modified_gray" ON "config_info_gray" USING btree ("gmt_modified");
|
||||
|
||||
ALTER TABLE "config_info_gray" ADD CONSTRAINT "config_info_gray_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of config_info_gray
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for config_tags_relation
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "config_tags_relation";
|
||||
CREATE TABLE "config_tags_relation" (
|
||||
"id" bigint NOT NULL,
|
||||
"tag_name" varchar(128) NOT NULL,
|
||||
"tag_type" varchar(64) ,
|
||||
"data_id" varchar(255) NOT NULL,
|
||||
"group_id" varchar(128) NOT NULL,
|
||||
"tenant_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"nid" bigserial NOT NULL
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "config_tags_relation"."id" IS 'id';
|
||||
COMMENT ON COLUMN "config_tags_relation"."tag_name" IS 'tag_name';
|
||||
COMMENT ON COLUMN "config_tags_relation"."tag_type" IS 'tag_type';
|
||||
COMMENT ON COLUMN "config_tags_relation"."data_id" IS 'data_id';
|
||||
COMMENT ON COLUMN "config_tags_relation"."group_id" IS 'group_id';
|
||||
COMMENT ON COLUMN "config_tags_relation"."tenant_id" IS 'tenant_id';
|
||||
COMMENT ON TABLE "config_tags_relation" IS 'config_tag_relation';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of config_tags_relation
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for group_capacity
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "group_capacity";
|
||||
CREATE TABLE "group_capacity" (
|
||||
"id" bigserial NOT NULL,
|
||||
"group_id" varchar(128) NOT NULL,
|
||||
"quota" int4 NOT NULL,
|
||||
"usage" int4 NOT NULL,
|
||||
"max_size" int4 NOT NULL,
|
||||
"max_aggr_count" int4 NOT NULL,
|
||||
"max_aggr_size" int4 NOT NULL,
|
||||
"max_history_count" int4 NOT NULL DEFAULT 0,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "group_capacity"."id" IS '主键ID';
|
||||
COMMENT ON COLUMN "group_capacity"."group_id" IS 'Group ID,空字符表示整个集群';
|
||||
COMMENT ON COLUMN "group_capacity"."quota" IS '配额,0表示使用默认值';
|
||||
COMMENT ON COLUMN "group_capacity"."usage" IS '使用量';
|
||||
COMMENT ON COLUMN "group_capacity"."max_size" IS '单个配置大小上限,单位为字节,0表示使用默认值';
|
||||
COMMENT ON COLUMN "group_capacity"."max_aggr_count" IS '聚合子配置最大个数,,0表示使用默认值';
|
||||
COMMENT ON COLUMN "group_capacity"."max_aggr_size" IS '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值';
|
||||
COMMENT ON COLUMN "group_capacity"."max_history_count" IS '最大变更历史数量';
|
||||
COMMENT ON COLUMN "group_capacity"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "group_capacity"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON TABLE "group_capacity" IS '集群、各Group容量信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of group_capacity
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for his_config_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "his_config_info";
|
||||
CREATE TABLE "his_config_info" (
|
||||
"id" int8 NOT NULL,
|
||||
"nid" bigserial NOT NULL,
|
||||
"data_id" varchar(255) NOT NULL,
|
||||
"group_id" varchar(128) NOT NULL,
|
||||
"app_name" varchar(128) ,
|
||||
"content" text NOT NULL,
|
||||
"md5" varchar(32) ,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"src_user" text ,
|
||||
"src_ip" varchar(20) ,
|
||||
"op_type" char(10) ,
|
||||
"tenant_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"encrypted_data_key" text NOT NULL,
|
||||
"publish_type" varchar(50) DEFAULT 'formal',
|
||||
"gray_name" varchar(50),
|
||||
"ext_info" text
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "his_config_info"."app_name" IS 'app_name';
|
||||
COMMENT ON COLUMN "his_config_info"."tenant_id" IS '租户字段';
|
||||
COMMENT ON COLUMN "his_config_info"."encrypted_data_key" IS '秘钥';
|
||||
COMMENT ON COLUMN "his_config_info"."publish_type" IS 'publish type gray or formal';
|
||||
COMMENT ON COLUMN "his_config_info"."gray_name" IS 'gray name';
|
||||
COMMENT ON COLUMN "his_config_info"."ext_info" IS 'ext info';
|
||||
COMMENT ON TABLE "his_config_info" IS '多租户改造';
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for permissions
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "permissions";
|
||||
CREATE TABLE "permissions" (
|
||||
"role" varchar(50) NOT NULL,
|
||||
"resource" varchar(512) NOT NULL,
|
||||
"action" varchar(8) NOT NULL
|
||||
)
|
||||
;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of permissions
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for roles
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "roles";
|
||||
CREATE TABLE "roles" (
|
||||
"username" varchar(50) NOT NULL,
|
||||
"role" varchar(50) NOT NULL
|
||||
)
|
||||
;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of roles
|
||||
-- ----------------------------
|
||||
-- No seed rows: MySQL schema also leaves `roles` empty so the console can run first-time admin setup.
|
||||
-- A row like ('nacos', 'ROLE_ADMIN') blocks that flow when the DB account name is `nacos` (common JDBC user).
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tenant_capacity
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "tenant_capacity";
|
||||
CREATE TABLE "tenant_capacity" (
|
||||
"id" bigserial NOT NULL,
|
||||
"tenant_id" varchar(128) NOT NULL,
|
||||
"quota" int4 NOT NULL,
|
||||
"usage" int4 NOT NULL,
|
||||
"max_size" int4 NOT NULL,
|
||||
"max_aggr_count" int4 NOT NULL,
|
||||
"max_aggr_size" int4 NOT NULL,
|
||||
"max_history_count" int4 NOT NULL DEFAULT 0,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "tenant_capacity"."id" IS '主键ID';
|
||||
COMMENT ON COLUMN "tenant_capacity"."tenant_id" IS 'Tenant ID';
|
||||
COMMENT ON COLUMN "tenant_capacity"."quota" IS '配额,0表示使用默认值';
|
||||
COMMENT ON COLUMN "tenant_capacity"."usage" IS '使用量';
|
||||
COMMENT ON COLUMN "tenant_capacity"."max_size" IS '单个配置大小上限,单位为字节,0表示使用默认值';
|
||||
COMMENT ON COLUMN "tenant_capacity"."max_aggr_count" IS '聚合子配置最大个数';
|
||||
COMMENT ON COLUMN "tenant_capacity"."max_aggr_size" IS '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值';
|
||||
COMMENT ON COLUMN "tenant_capacity"."max_history_count" IS '最大变更历史数量';
|
||||
COMMENT ON COLUMN "tenant_capacity"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "tenant_capacity"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON TABLE "tenant_capacity" IS '租户容量信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tenant_capacity
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tenant_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "tenant_info";
|
||||
CREATE TABLE "tenant_info" (
|
||||
"id" bigserial NOT NULL,
|
||||
"kp" varchar(128) NOT NULL,
|
||||
"tenant_id" varchar(128) ,
|
||||
"tenant_name" varchar(128) ,
|
||||
"tenant_desc" varchar(256) ,
|
||||
"create_source" varchar(32) ,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "tenant_info"."id" IS 'id';
|
||||
COMMENT ON COLUMN "tenant_info"."kp" IS 'kp';
|
||||
COMMENT ON COLUMN "tenant_info"."tenant_id" IS 'tenant_id';
|
||||
COMMENT ON COLUMN "tenant_info"."tenant_name" IS 'tenant_name';
|
||||
COMMENT ON COLUMN "tenant_info"."tenant_desc" IS 'tenant_desc';
|
||||
COMMENT ON COLUMN "tenant_info"."create_source" IS 'create_source';
|
||||
COMMENT ON COLUMN "tenant_info"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "tenant_info"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON TABLE "tenant_info" IS 'tenant_info';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tenant_info
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for users
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "users";
|
||||
CREATE TABLE "users" (
|
||||
"username" varchar(50) NOT NULL,
|
||||
"password" varchar(500) NOT NULL,
|
||||
"enabled" boolean NOT NULL
|
||||
)
|
||||
;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of users
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table config_info
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_configinfo_datagrouptenant" ON "config_info" ("data_id","group_id","tenant_id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table config_info
|
||||
-- ----------------------------
|
||||
ALTER TABLE "config_info" ADD CONSTRAINT "config_info_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table config_tags_relation
|
||||
-- ----------------------------
|
||||
CREATE INDEX "idx_tenant_id" ON "config_tags_relation" USING btree (
|
||||
"tenant_id"
|
||||
);
|
||||
CREATE UNIQUE INDEX "uk_configtagrelation_configidtag" ON "config_tags_relation" USING btree (
|
||||
"id",
|
||||
"tag_name",
|
||||
"tag_type"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table config_tags_relation
|
||||
-- ----------------------------
|
||||
ALTER TABLE "config_tags_relation" ADD CONSTRAINT "config_tags_relation_pkey" PRIMARY KEY ("nid");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table group_capacity
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_group_id" ON "group_capacity" USING btree (
|
||||
"group_id"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table group_capacity
|
||||
-- ----------------------------
|
||||
ALTER TABLE "group_capacity" ADD CONSTRAINT "group_capacity_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table his_config_info
|
||||
-- ----------------------------
|
||||
CREATE INDEX "idx_did" ON "his_config_info" USING btree (
|
||||
"data_id"
|
||||
);
|
||||
CREATE INDEX "idx_gmt_create" ON "his_config_info" USING btree (
|
||||
"gmt_create"
|
||||
);
|
||||
CREATE INDEX "idx_gmt_modified" ON "his_config_info" USING btree (
|
||||
"gmt_modified"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table his_config_info
|
||||
-- ----------------------------
|
||||
ALTER TABLE "his_config_info" ADD CONSTRAINT "his_config_info_pkey" PRIMARY KEY ("nid");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table permissions
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_role_permission" ON "permissions" USING btree (
|
||||
"role",
|
||||
"resource",
|
||||
"action"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table roles
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_username_role" ON "roles" USING btree (
|
||||
"username",
|
||||
"role"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table tenant_capacity
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_tenant_id" ON "tenant_capacity" USING btree (
|
||||
"tenant_id"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table tenant_capacity
|
||||
-- ----------------------------
|
||||
ALTER TABLE "tenant_capacity" ADD CONSTRAINT "tenant_capacity_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table tenant_info
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_tenant_info_kptenantid" ON "tenant_info" USING btree (
|
||||
"kp",
|
||||
"tenant_id"
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pipeline_execution
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "pipeline_execution";
|
||||
CREATE TABLE "pipeline_execution" (
|
||||
"execution_id" varchar(64) NOT NULL,
|
||||
"resource_type" varchar(32) NOT NULL,
|
||||
"resource_name" varchar(256) NOT NULL,
|
||||
"namespace_id" varchar(128) DEFAULT NULL,
|
||||
"version" varchar(64) DEFAULT NULL,
|
||||
"status" varchar(32) NOT NULL,
|
||||
"pipeline" text NOT NULL,
|
||||
"create_time" bigint NOT NULL,
|
||||
"update_time" bigint NOT NULL
|
||||
);
|
||||
COMMENT ON COLUMN "pipeline_execution"."execution_id" IS '执行ID';
|
||||
COMMENT ON COLUMN "pipeline_execution"."resource_type" IS '资源类型';
|
||||
COMMENT ON COLUMN "pipeline_execution"."resource_name" IS '资源名称';
|
||||
COMMENT ON COLUMN "pipeline_execution"."namespace_id" IS '命名空间ID';
|
||||
COMMENT ON COLUMN "pipeline_execution"."version" IS '版本';
|
||||
COMMENT ON COLUMN "pipeline_execution"."status" IS '执行状态';
|
||||
COMMENT ON COLUMN "pipeline_execution"."pipeline" IS 'pipeline节点结果JSON';
|
||||
COMMENT ON COLUMN "pipeline_execution"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "pipeline_execution"."update_time" IS '修改时间';
|
||||
COMMENT ON TABLE "pipeline_execution" IS 'AI资源发布审核Pipeline执行记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table pipeline_execution
|
||||
-- ----------------------------
|
||||
ALTER TABLE "pipeline_execution" ADD CONSTRAINT "pipeline_execution_pkey" PRIMARY KEY ("execution_id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for ai_resource
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "ai_resource";
|
||||
CREATE TABLE "ai_resource" (
|
||||
"id" bigserial NOT NULL,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"name" varchar(256) NOT NULL,
|
||||
"type" varchar(32) NOT NULL,
|
||||
"c_desc" varchar(1024),
|
||||
"status" varchar(32),
|
||||
"namespace_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"biz_tags" varchar(1024),
|
||||
"ext" text,
|
||||
"c_from" varchar(256) NOT NULL DEFAULT 'local',
|
||||
"version_info" text,
|
||||
"meta_version" bigint NOT NULL DEFAULT 1,
|
||||
"scope" varchar(16) NOT NULL DEFAULT 'PRIVATE',
|
||||
"owner" varchar(128) NOT NULL DEFAULT '',
|
||||
"download_count" bigint NOT NULL DEFAULT 0
|
||||
)
|
||||
;
|
||||
|
||||
COMMENT ON COLUMN "ai_resource"."id" IS 'id';
|
||||
COMMENT ON COLUMN "ai_resource"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "ai_resource"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON COLUMN "ai_resource"."name" IS '资源名称';
|
||||
COMMENT ON COLUMN "ai_resource"."type" IS '资源类型';
|
||||
COMMENT ON COLUMN "ai_resource"."c_desc" IS '资源描述';
|
||||
COMMENT ON COLUMN "ai_resource"."status" IS '资源状态';
|
||||
COMMENT ON COLUMN "ai_resource"."namespace_id" IS '命名空间ID';
|
||||
COMMENT ON COLUMN "ai_resource"."biz_tags" IS '业务标签';
|
||||
COMMENT ON COLUMN "ai_resource"."ext" IS '扩展信息(JSON)';
|
||||
COMMENT ON COLUMN "ai_resource"."c_from" IS '来源标识(导入/同步来源)';
|
||||
COMMENT ON COLUMN "ai_resource"."version_info" IS '版本信息(JSON)';
|
||||
COMMENT ON COLUMN "ai_resource"."meta_version" IS '元数据版本(乐观锁)';
|
||||
COMMENT ON COLUMN "ai_resource"."scope" IS '可见性: PUBLIC/PRIVATE';
|
||||
COMMENT ON COLUMN "ai_resource"."owner" IS '创建者用户名';
|
||||
COMMENT ON COLUMN "ai_resource"."download_count" IS '下载次数';
|
||||
COMMENT ON TABLE "ai_resource" IS 'AI资源元数据表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table ai_resource
|
||||
-- ----------------------------
|
||||
ALTER TABLE "ai_resource" ADD CONSTRAINT "ai_resource_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table ai_resource
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_ai_resource_ns_name_type" ON "ai_resource" USING btree (
|
||||
"namespace_id",
|
||||
"name",
|
||||
"type",
|
||||
"c_from"
|
||||
);
|
||||
CREATE INDEX "idx_ai_resource_name" ON "ai_resource" USING btree ("name");
|
||||
CREATE INDEX "idx_ai_resource_type" ON "ai_resource" USING btree ("type");
|
||||
CREATE INDEX "idx_ai_resource_gmt_modified" ON "ai_resource" USING btree ("gmt_modified");
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for ai_resource_version
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "ai_resource_version";
|
||||
CREATE TABLE "ai_resource_version" (
|
||||
"id" bigserial NOT NULL,
|
||||
"gmt_create" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"gmt_modified" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"type" varchar(32) NOT NULL,
|
||||
"author" varchar(128),
|
||||
"name" varchar(256) NOT NULL,
|
||||
"c_desc" varchar(1024),
|
||||
"status" varchar(32) NOT NULL,
|
||||
"version" varchar(64) NOT NULL,
|
||||
"namespace_id" varchar(128) NOT NULL DEFAULT '',
|
||||
"storage" text,
|
||||
"publish_pipeline_info" text,
|
||||
"download_count" bigint NOT NULL DEFAULT 0
|
||||
)
|
||||
;
|
||||
|
||||
COMMENT ON COLUMN "ai_resource_version"."id" IS 'id';
|
||||
COMMENT ON COLUMN "ai_resource_version"."gmt_create" IS '创建时间';
|
||||
COMMENT ON COLUMN "ai_resource_version"."gmt_modified" IS '修改时间';
|
||||
COMMENT ON COLUMN "ai_resource_version"."type" IS '资源类型';
|
||||
COMMENT ON COLUMN "ai_resource_version"."author" IS '作者';
|
||||
COMMENT ON COLUMN "ai_resource_version"."name" IS '资源名称';
|
||||
COMMENT ON COLUMN "ai_resource_version"."c_desc" IS '版本描述';
|
||||
COMMENT ON COLUMN "ai_resource_version"."status" IS '版本状态';
|
||||
COMMENT ON COLUMN "ai_resource_version"."version" IS '版本号';
|
||||
COMMENT ON COLUMN "ai_resource_version"."namespace_id" IS '命名空间ID';
|
||||
COMMENT ON COLUMN "ai_resource_version"."storage" IS '存储信息(JSON)';
|
||||
COMMENT ON COLUMN "ai_resource_version"."publish_pipeline_info" IS '发布流水线信息(JSON)';
|
||||
COMMENT ON COLUMN "ai_resource_version"."download_count" IS '下载次数';
|
||||
COMMENT ON TABLE "ai_resource_version" IS 'AI资源版本表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table ai_resource_version
|
||||
-- ----------------------------
|
||||
ALTER TABLE "ai_resource_version" ADD CONSTRAINT "ai_resource_version_pkey" PRIMARY KEY ("id");
|
||||
|
||||
-- ----------------------------
|
||||
-- Indexes structure for table ai_resource_version
|
||||
-- ----------------------------
|
||||
CREATE UNIQUE INDEX "uk_ai_resource_ver_ns_name_type_ver" ON "ai_resource_version" USING btree (
|
||||
"namespace_id",
|
||||
"name",
|
||||
"type",
|
||||
"version"
|
||||
);
|
||||
CREATE INDEX "idx_ai_resource_ver_name" ON "ai_resource_version" USING btree ("name");
|
||||
CREATE INDEX "idx_ai_resource_ver_status" ON "ai_resource_version" USING btree ("status");
|
||||
CREATE INDEX "idx_ai_resource_ver_gmt_modified" ON "ai_resource_version" USING btree ("gmt_modified");
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
-- PostgreSQL upgrade script for deployments that still contain nullable tenant_id
|
||||
-- values in config-related tables.
|
||||
--
|
||||
-- IMPORTANT:
|
||||
-- 1. Review and clean duplicate logical rows before replacing NULL tenant_id
|
||||
-- values with '' on config_info, otherwise the UPDATE may conflict with the
|
||||
-- existing unique index on (data_id, group_id, tenant_id).
|
||||
-- 2. Apply this script before upgrading to a Nacos build that validates the
|
||||
-- PostgreSQL tenant schema on startup.
|
||||
--
|
||||
-- Suggested pre-check for duplicate logical config rows:
|
||||
-- SELECT data_id, group_id, COUNT(*)
|
||||
-- FROM config_info
|
||||
-- WHERE tenant_id IS NULL
|
||||
-- GROUP BY data_id, group_id
|
||||
-- HAVING COUNT(*) > 1;
|
||||
|
||||
ALTER TABLE config_info ALTER COLUMN tenant_id SET DEFAULT '';
|
||||
UPDATE config_info SET tenant_id = '' WHERE tenant_id IS NULL;
|
||||
ALTER TABLE config_info ALTER COLUMN tenant_id SET NOT NULL;
|
||||
|
||||
ALTER TABLE config_info_gray ALTER COLUMN tenant_id SET DEFAULT '';
|
||||
UPDATE config_info_gray SET tenant_id = '' WHERE tenant_id IS NULL;
|
||||
ALTER TABLE config_info_gray ALTER COLUMN tenant_id SET NOT NULL;
|
||||
|
||||
ALTER TABLE config_tags_relation ALTER COLUMN tenant_id SET DEFAULT '';
|
||||
UPDATE config_tags_relation SET tenant_id = '' WHERE tenant_id IS NULL;
|
||||
ALTER TABLE config_tags_relation ALTER COLUMN tenant_id SET NOT NULL;
|
||||
|
||||
ALTER TABLE his_config_info ALTER COLUMN tenant_id SET DEFAULT '';
|
||||
UPDATE his_config_info SET tenant_id = '' WHERE tenant_id IS NULL;
|
||||
ALTER TABLE his_config_info ALTER COLUMN tenant_id SET NOT NULL;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
com.alibaba.nacos.plugin.datasource.impl.dialect.PostgresqlDatabaseDialect
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigInfoGrayMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.ConfigTagsRelationMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.GroupCapacityMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.HistoryConfigInfoMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.TenantCapacityMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.TenantInfoMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.AiResourceMapperByPostgresql
|
||||
com.alibaba.nacos.plugin.datasource.impl.postgresql.AiResourceVersionMapperByPostgresql
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.enums.postgresql;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* TrustedPostgresqlFunctionEnumTest
|
||||
*
|
||||
* @author Ken
|
||||
*/
|
||||
public class TrustedPostgresqlFunctionEnumTest {
|
||||
|
||||
@Test
|
||||
void testGetFunctionByName() {
|
||||
Assertions.assertEquals("NOW()", TrustedPostgresqlFunctionEnum.getFunctionByName("NOW()"));
|
||||
}
|
||||
|
||||
@Test()
|
||||
void testGetFunctionByErrorName() {
|
||||
Assertions.assertThrows(IllegalArgumentException.class,
|
||||
() -> TrustedPostgresqlFunctionEnum.getFunctionByName("UNKNOWN"));
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.ContextConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.TableConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* ConfigInfoMapperByPostgresqlTest
|
||||
*
|
||||
* @author Ken
|
||||
*/
|
||||
class ConfigInfoMapperByPostgresqlTest {
|
||||
|
||||
int startRow = 0;
|
||||
|
||||
int pageSize = 5;
|
||||
|
||||
String appName = "appName";
|
||||
|
||||
String groupId = "groupId";
|
||||
|
||||
String tenantId = "tenantId";
|
||||
|
||||
String dataId = "dataId";
|
||||
|
||||
String id = "id";
|
||||
|
||||
MapperContext context;
|
||||
|
||||
private ConfigInfoMapperByPostgresql configInfoMapperByPostgresql;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
configInfoMapperByPostgresql = new ConfigInfoMapperByPostgresql();
|
||||
|
||||
context = new MapperContext(startRow, pageSize);
|
||||
context.putWhereParameter(FieldConstant.ID, id);
|
||||
|
||||
context.putWhereParameter(FieldConstant.APP_NAME, appName);
|
||||
context.putWhereParameter(FieldConstant.TENANT_ID, tenantId);
|
||||
context.putWhereParameter(FieldConstant.GROUP_ID, groupId);
|
||||
context.putWhereParameter(FieldConstant.DATA_ID, dataId);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAllConfigInfoFragment() {
|
||||
//with content
|
||||
context.putContextParameter(ContextConstant.NEED_CONTENT, "true");
|
||||
|
||||
MapperResult needContentMapperResult =
|
||||
configInfoMapperByPostgresql.findAllConfigInfoFragment(context);
|
||||
assertEquals(
|
||||
"SELECT id,data_id,group_id,tenant_id,app_name,content,md5,gmt_modified,type,encrypted_data_key "
|
||||
+ "FROM config_info WHERE id > ? ORDER BY id ASC OFFSET " + startRow + " LIMIT "
|
||||
+ pageSize,
|
||||
needContentMapperResult.getSql());
|
||||
assertArrayEquals(new Object[] {id}, needContentMapperResult.getParamList().toArray());
|
||||
|
||||
//without content
|
||||
context.putContextParameter(ContextConstant.NEED_CONTENT, "false");
|
||||
MapperResult withoutContentMapperResult =
|
||||
configInfoMapperByPostgresql.findAllConfigInfoFragment(context);
|
||||
assertEquals(
|
||||
"SELECT id,data_id,group_id,tenant_id,app_name,md5,gmt_modified,type,encrypted_data_key "
|
||||
+ "FROM config_info WHERE id > ? ORDER BY id ASC OFFSET " + startRow + " LIMIT "
|
||||
+ pageSize,
|
||||
withoutContentMapperResult.getSql());
|
||||
assertArrayEquals(new Object[] {id}, withoutContentMapperResult.getParamList().toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindConfigInfo4PageFetchRows() {
|
||||
MapperResult mapperResult =
|
||||
configInfoMapperByPostgresql.findConfigInfo4PageFetchRows(context);
|
||||
|
||||
assertEquals(
|
||||
"SELECT id,data_id,group_id,tenant_id,app_name,content,md5,type,encrypted_data_key,c_desc "
|
||||
+ "FROM config_info WHERE tenant_id=? AND data_id=? AND group_id=? AND app_name=? "
|
||||
+ "OFFSET " + startRow + " LIMIT " + pageSize,
|
||||
mapperResult.getSql());
|
||||
assertArrayEquals(new Object[] {tenantId, dataId, groupId, appName},
|
||||
mapperResult.getParamList().toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindConfigInfoLike4PageFetchRows() {
|
||||
MapperResult mapperResult =
|
||||
configInfoMapperByPostgresql.findConfigInfoLike4PageFetchRows(context);
|
||||
assertEquals(
|
||||
"SELECT id,data_id,group_id,tenant_id,app_name,content,md5,encrypted_data_key,type,c_desc "
|
||||
+ "FROM config_info WHERE tenant_id LIKE ? AND data_id LIKE ? AND group_id LIKE ? AND app_name = ? "
|
||||
+ "OFFSET " + startRow + " LIMIT " + pageSize,
|
||||
mapperResult.getSql());
|
||||
assertArrayEquals(new Object[] {tenantId, dataId, groupId, appName},
|
||||
mapperResult.getParamList().toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindConfigInfoBaseLikeFetchRows() {
|
||||
MapperResult mapperResult =
|
||||
configInfoMapperByPostgresql.findConfigInfoBaseLikeFetchRows(context);
|
||||
assertEquals("SELECT id,data_id,group_id,tenant_id,content FROM config_info WHERE "
|
||||
+ " 1=1 AND tenant_id='' AND data_id LIKE ? AND group_id LIKE ? "
|
||||
+ "OFFSET " + startRow + " LIMIT " + pageSize, mapperResult.getSql());
|
||||
assertArrayEquals(new Object[] {dataId, groupId}, mapperResult.getParamList().toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetTableName() {
|
||||
String tableName = configInfoMapperByPostgresql.getTableName();
|
||||
assertEquals(TableConstant.CONFIG_INFO, tableName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetDataSource() {
|
||||
String dataSource = configInfoMapperByPostgresql.getDataSource();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, dataSource);
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* ConfigTagsRelationMapperByPostgresqlTest
|
||||
*
|
||||
* @author Ken
|
||||
*/
|
||||
public class ConfigTagsRelationMapperByPostgresqlTest {
|
||||
|
||||
int startRow = 0;
|
||||
|
||||
int pageSize = 5;
|
||||
|
||||
String tenantId = "tenantId";
|
||||
|
||||
String dataId = "dataId";
|
||||
|
||||
String groupId = "groupId";
|
||||
|
||||
String appName = "appName";
|
||||
|
||||
String content = "content";
|
||||
|
||||
String[] tagArr = new String[] {"tagA", "tagB", "tagC"};
|
||||
|
||||
String[] typeArr = new String[] {"text", "json", "xml", "yaml", "properties"};
|
||||
|
||||
MapperContext context;
|
||||
|
||||
private ConfigTagsRelationMapperByPostgresql configTagsRelationMapperByPostgresql;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
configTagsRelationMapperByPostgresql = new ConfigTagsRelationMapperByPostgresql();
|
||||
context = new MapperContext(startRow, pageSize);
|
||||
|
||||
context.putWhereParameter(FieldConstant.TENANT_ID, tenantId);
|
||||
context.putWhereParameter(FieldConstant.DATA_ID, dataId);
|
||||
context.putWhereParameter(FieldConstant.GROUP_ID, groupId);
|
||||
context.putWhereParameter(FieldConstant.APP_NAME, appName);
|
||||
context.putWhereParameter(FieldConstant.CONTENT, content);
|
||||
|
||||
context.putWhereParameter(FieldConstant.TAG_ARR, tagArr);
|
||||
context.putWhereParameter(FieldConstant.TYPE, typeArr);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindConfigInfoLike4PageFetchRows() {
|
||||
MapperResult mapperResult =
|
||||
configTagsRelationMapperByPostgresql.findConfigInfoLike4PageFetchRows(context);
|
||||
String sql = mapperResult.getSql();
|
||||
// 验证是否存在标量子查询
|
||||
assertTrue(sql.contains(
|
||||
"(SELECT STRING_AGG(tag_name, ',') FROM config_tags_relation d WHERE d.id = c.id)"));
|
||||
// 验证是否存在EXISTS
|
||||
assertTrue(sql.contains(" EXISTS "));
|
||||
// 验证是否存在标签的子查询
|
||||
assertTrue(sql.contains("SELECT 1 FROM config_tags_relation"));
|
||||
|
||||
assertEquals(
|
||||
"SELECT c.id,c.data_id,c.group_id,c.tenant_id,c.app_name,c.content,c.md5,c.encrypted_data_key,"
|
||||
+ "c.type,c.c_desc,(SELECT STRING_AGG(tag_name, ',') FROM config_tags_relation d WHERE d.id = c.id) as config_tags "
|
||||
+ "FROM (SELECT a.id,a.data_id,a.group_id,a.tenant_id,a.app_name,a.content,a.md5,a.encrypted_data_key,a.type,a.c_desc "
|
||||
+ "FROM config_info a WHERE a.tenant_id LIKE ? AND a.data_id LIKE ? AND a.group_id LIKE ? AND a.app_name = ? "
|
||||
+ "AND a.content LIKE ? AND EXISTS ( SELECT 1 FROM config_tags_relation b WHERE b.id = a.id "
|
||||
+ "AND ( b.tag_name LIKE ? OR b.tag_name LIKE ? OR b.tag_name LIKE ? ) ) AND a.type IN (?, ?, ?, ?, ?) "
|
||||
+ "OFFSET " + startRow + " ROWS FETCH NEXT " + pageSize + " ROWS ONLY) c ",
|
||||
mapperResult.getSql());
|
||||
|
||||
List<Object> expectedParams = new ArrayList<>();
|
||||
expectedParams.add(tenantId);
|
||||
expectedParams.add(dataId);
|
||||
expectedParams.add(groupId);
|
||||
expectedParams.add(appName);
|
||||
expectedParams.add(content);
|
||||
expectedParams.addAll(Arrays.asList(tagArr));
|
||||
expectedParams.addAll(Arrays.asList(typeArr));
|
||||
assertArrayEquals(expectedParams.toArray(), mapperResult.getParamList().toArray());
|
||||
}
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.NamespaceUtil;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.DatabaseTypeConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.FieldConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.constants.TableConstant;
|
||||
import com.alibaba.nacos.plugin.datasource.impl.dialect.PostgresqlDatabaseDialect;
|
||||
import com.alibaba.nacos.plugin.datasource.mapper.AiResourceMapper;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperContext;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class PostgresqlMapperCoverageTest {
|
||||
|
||||
private final int startRow = 3;
|
||||
|
||||
private final int pageSize = 7;
|
||||
|
||||
private final String tenantId = "tenantId";
|
||||
|
||||
private final String groupId = "groupId";
|
||||
|
||||
private final String namespaceId = "namespaceId";
|
||||
|
||||
private final long modifiedTime = 1000L;
|
||||
|
||||
private MapperContext context;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
context = new MapperContext(startRow, pageSize);
|
||||
context.putWhereParameter(FieldConstant.TENANT_ID, tenantId);
|
||||
context.putWhereParameter(FieldConstant.GROUP_ID, groupId);
|
||||
context.putWhereParameter(FieldConstant.NAMESPACE_ID, namespaceId);
|
||||
context.putWhereParameter(FieldConstant.NAME, "nacos");
|
||||
context.putWhereParameter(FieldConstant.TYPE, "mcp");
|
||||
context.putWhereParameter(FieldConstant.STATUS, "stable");
|
||||
context.putWhereParameter(FieldConstant.VERSION, "1.0.0");
|
||||
context.putWhereParameter(FieldConstant.ID, 12L);
|
||||
context.putWhereParameter(FieldConstant.LIMIT_SIZE, 20);
|
||||
context.putWhereParameter(FieldConstant.START_TIME, modifiedTime);
|
||||
context.putWhereParameter(FieldConstant.DATA_ID, "dataId");
|
||||
context.putUpdateParameter(FieldConstant.GROUP_ID, groupId);
|
||||
context.putUpdateParameter(FieldConstant.TENANT_ID, tenantId);
|
||||
context.putUpdateParameter(FieldConstant.QUOTA, 10);
|
||||
context.putUpdateParameter(FieldConstant.MAX_SIZE, 100);
|
||||
context.putUpdateParameter(FieldConstant.MAX_AGGR_COUNT, 5);
|
||||
context.putUpdateParameter(FieldConstant.MAX_AGGR_SIZE, 200);
|
||||
context.putUpdateParameter(FieldConstant.GMT_CREATE, 100L);
|
||||
context.putUpdateParameter(FieldConstant.GMT_MODIFIED, modifiedTime);
|
||||
context.putWhereParameter(FieldConstant.USAGE, 99);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostgresqlDatabaseDialect() {
|
||||
PostgresqlDatabaseDialect dialect = new PostgresqlDatabaseDialect();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, dialect.getType());
|
||||
assertEquals("NOW()", dialect.getFunction("NOW()"));
|
||||
assertEquals("SELECT OFFSET ? LIMIT ? ", dialect.getLimitPageSqlWithMark("SELECT"));
|
||||
assertEquals("SELECT OFFSET 14 LIMIT 7", dialect.getLimitPageSql("SELECT", 3, 7));
|
||||
assertEquals("SELECT OFFSET 3 LIMIT 7",
|
||||
dialect.getLimitPageSqlWithOffset("SELECT", 3, 7));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTenantInfoMapperInsertAndUpdate() {
|
||||
TenantInfoMapperByPostgresql mapper = new TenantInfoMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertEquals(TableConstant.TENANT_INFO, mapper.getTableName());
|
||||
assertEquals(
|
||||
"INSERT INTO tenant_info(gmt_create, tenant_id, gmt_modified) "
|
||||
+ "VALUES(TO_TIMESTAMP(? / 1000.0),?,NOW())",
|
||||
mapper.insert(Arrays.asList("gmt_create", "tenant_id", "gmt_modified@NOW()")));
|
||||
assertEquals(
|
||||
"UPDATE tenant_info SET gmt_modified = TO_TIMESTAMP(? / 1000.0),"
|
||||
+ "tenant_id = ?,gmt_create = NOW() WHERE tenant_id = ?",
|
||||
mapper.update(Arrays.asList("gmt_modified", "tenant_id", "gmt_create@NOW()"),
|
||||
Collections.singletonList("tenant_id")));
|
||||
assertEquals("UPDATE tenant_info SET tenant_id = ?",
|
||||
mapper.update(Collections.singletonList("tenant_id"), Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGroupCapacityMapper() {
|
||||
GroupCapacityMapperByPostgresql mapper = new GroupCapacityMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertResult(mapper.select(context),
|
||||
"SELECT id, quota, usage, max_size, max_aggr_count, max_aggr_size, group_id "
|
||||
+ "FROM group_capacity WHERE group_id = ?",
|
||||
groupId);
|
||||
assertResult(mapper.insertIntoSelect(context),
|
||||
"INSERT INTO group_capacity (group_id, quota, usage, max_size, max_aggr_count,"
|
||||
+ " max_aggr_size, max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info",
|
||||
groupId, 10, 100, 5, 200, 100L, modifiedTime);
|
||||
assertResult(mapper.insertIntoSelectByWhere(context),
|
||||
"INSERT INTO group_capacity (group_id, quota, usage, max_size, max_aggr_count,"
|
||||
+ " max_aggr_size, max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info "
|
||||
+ "WHERE group_id=? AND tenant_id = '" + NamespaceUtil
|
||||
.getNamespaceDefaultId()
|
||||
+ "'",
|
||||
groupId, 10, 100, 5, 200, 100L, modifiedTime, groupId);
|
||||
assertResult(mapper.incrementUsageByWhereQuotaEqualZero(context),
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? "
|
||||
+ "WHERE group_id = ? AND usage < ? AND quota = 0",
|
||||
modifiedTime, groupId, 99);
|
||||
assertResult(mapper.incrementUsageByWhereQuotaNotEqualZero(context),
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? "
|
||||
+ "WHERE group_id = ? AND usage < quota AND quota != 0",
|
||||
modifiedTime, groupId);
|
||||
assertResult(mapper.incrementUsageByWhere(context),
|
||||
"UPDATE group_capacity SET usage = usage + 1, gmt_modified = ? WHERE group_id = ?",
|
||||
modifiedTime, groupId);
|
||||
assertResult(mapper.decrementUsageByWhere(context),
|
||||
"UPDATE group_capacity SET usage = usage - 1, gmt_modified = ? "
|
||||
+ "WHERE group_id = ? AND usage > 0",
|
||||
modifiedTime, groupId);
|
||||
assertResult(mapper.updateUsage(context),
|
||||
"UPDATE group_capacity SET usage = (SELECT count(*) FROM config_info), "
|
||||
+ "gmt_modified = ? WHERE group_id = ?",
|
||||
modifiedTime, groupId);
|
||||
assertResult(mapper.updateUsageByWhere(context),
|
||||
"UPDATE group_capacity SET usage = (SELECT count(*) FROM config_info "
|
||||
+ "WHERE group_id=? AND tenant_id = '" + NamespaceUtil
|
||||
.getNamespaceDefaultId()
|
||||
+ "'), gmt_modified = ? WHERE group_id= ?",
|
||||
groupId, modifiedTime, groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTenantCapacityMapper() {
|
||||
TenantCapacityMapperByPostgresql mapper = new TenantCapacityMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertResult(mapper.select(context),
|
||||
"SELECT id, quota, usage, max_size, max_aggr_count, max_aggr_size, tenant_id "
|
||||
+ "FROM tenant_capacity WHERE tenant_id = ?",
|
||||
tenantId);
|
||||
assertResult(mapper.incrementUsageWithDefaultQuotaLimit(context),
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? "
|
||||
+ "WHERE tenant_id = ? AND usage < ? AND quota = 0",
|
||||
modifiedTime, tenantId, 99);
|
||||
assertResult(mapper.incrementUsageWithQuotaLimit(context),
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? "
|
||||
+ "WHERE tenant_id = ? AND usage < quota AND quota != 0",
|
||||
modifiedTime, tenantId);
|
||||
assertResult(mapper.incrementUsage(context),
|
||||
"UPDATE tenant_capacity SET usage = usage + 1, gmt_modified = ? "
|
||||
+ "WHERE tenant_id = ?",
|
||||
modifiedTime, tenantId);
|
||||
assertResult(mapper.decrementUsage(context),
|
||||
"UPDATE tenant_capacity SET usage = usage - 1, gmt_modified = ? "
|
||||
+ "WHERE tenant_id = ? AND usage > 0",
|
||||
modifiedTime, tenantId);
|
||||
assertResult(mapper.correctUsage(context),
|
||||
"UPDATE tenant_capacity SET usage = (SELECT count(*) FROM config_info "
|
||||
+ "WHERE tenant_id = ?), gmt_modified = ? WHERE tenant_id = ?",
|
||||
tenantId, modifiedTime, tenantId);
|
||||
assertResult(mapper.insertTenantCapacity(context),
|
||||
"INSERT INTO tenant_capacity (tenant_id, quota, usage, max_size, max_aggr_count, "
|
||||
+ "max_aggr_size, max_history_count, gmt_create, gmt_modified)"
|
||||
+ " SELECT ?, ?, count(*), ?, ?, ?, 0, ?, ? FROM config_info WHERE tenant_id=?",
|
||||
tenantId, 10, 100, 5, 200, 100L, modifiedTime, tenantId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHistoryConfigInfoMapper() {
|
||||
HistoryConfigInfoMapperByPostgresql mapper = new HistoryConfigInfoMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertEquals(TableConstant.HIS_CONFIG_INFO, mapper.getTableName());
|
||||
assertResult(mapper.removeConfigHistory(context),
|
||||
"WITH temp_table as (SELECT id FROM his_config_info WHERE gmt_modified < ? LIMIT ? ) "
|
||||
+ "DELETE FROM his_config_info WHERE id in (SELECT id FROM temp_table) ",
|
||||
modifiedTime, 20);
|
||||
assertResult(mapper.pageFindConfigHistoryFetchRows(context),
|
||||
"SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,ext_info,"
|
||||
+ "publish_type,gray_name,gmt_create,gmt_modified FROM his_config_info "
|
||||
+ "WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY nid DESC "
|
||||
+ "LIMIT 7 OFFSET 3",
|
||||
"dataId", groupId, tenantId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimplePostgresqlMappers() {
|
||||
ConfigInfoMapperByPostgresql configInfoMapper = new ConfigInfoMapperByPostgresql();
|
||||
assertEquals("NOW()", configInfoMapper.getFunction("NOW()"));
|
||||
|
||||
ConfigInfoGrayMapperByPostgresql grayMapper = new ConfigInfoGrayMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, grayMapper.getDataSource());
|
||||
assertEquals("NOW()", grayMapper.getFunction("NOW()"));
|
||||
assertEquals(TableConstant.CONFIG_INFO_GRAY, grayMapper.getTableName());
|
||||
assertResult(grayMapper.findAllConfigInfoGrayForDumpAllFetchRows(context),
|
||||
" SELECT id,data_id,group_id,tenant_id,gray_name,gray_rule,app_name,content,"
|
||||
+ "md5,gmt_modified FROM config_info_gray ORDER BY id LIMIT 7 OFFSET 3");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAiResourceMapper() {
|
||||
AiResourceMapperByPostgresql mapper = new AiResourceMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertEquals(TableConstant.AI_RESOURCE, mapper.getTableName());
|
||||
context.putWhereParameter(FieldConstant.BIZ_TAGS, "tag");
|
||||
context.putWhereParameter(FieldConstant.SCOPE, "public");
|
||||
context.putWhereParameter(FieldConstant.OWNER, "owner");
|
||||
context.putWhereParameter(FieldConstant.ORDER_BY, FieldConstant.ORDER_BY_DOWNLOAD_COUNT);
|
||||
assertResult(mapper.findAiResourceFetchRows(context),
|
||||
"SELECT id,gmt_create,gmt_modified,name,type,c_desc,status,namespace_id,biz_tags,"
|
||||
+ "ext,c_from,version_info,meta_version,scope,owner,download_count "
|
||||
+ "FROM ai_resource WHERE namespace_id = ? AND name LIKE ? "
|
||||
+ "AND biz_tags LIKE ? AND type = ? AND scope = ? AND owner = ? "
|
||||
+ "ORDER BY download_count DESC LIMIT 7 OFFSET 3",
|
||||
namespaceId, "nacos", "tag", "mcp", "public", "owner");
|
||||
|
||||
MapperContext alwaysEmptyContext = new MapperContext(startRow, pageSize);
|
||||
alwaysEmptyContext.putWhereParameter(FieldConstant.NAMESPACE_ID, namespaceId);
|
||||
alwaysEmptyContext.putWhereParameter(AiResourceMapper.QUERY_CONDITION_ALWAYS_EMPTY, true);
|
||||
assertResult(mapper.findAiResourceFetchRows(alwaysEmptyContext),
|
||||
"SELECT id,gmt_create,gmt_modified,name,type,c_desc,status,namespace_id,biz_tags,"
|
||||
+ "ext,c_from,version_info,meta_version,scope,owner,download_count "
|
||||
+ "FROM ai_resource WHERE namespace_id = ? AND 1 = ? "
|
||||
+ "ORDER BY gmt_modified DESC LIMIT 7 OFFSET 3",
|
||||
namespaceId, 0);
|
||||
|
||||
MapperContext orContext = new MapperContext(startRow, pageSize);
|
||||
orContext.putWhereParameter(FieldConstant.NAMESPACE_ID, namespaceId);
|
||||
Map<Object, Object> orGroup = new LinkedHashMap<>();
|
||||
orGroup.put(FieldConstant.STATUS, "stable");
|
||||
orGroup.put(FieldConstant.TYPE, Arrays.asList("mcp", "a2a"));
|
||||
orContext.putWhereParameter(AiResourceMapper.QUERY_CONDITION_OR_GROUP, orGroup);
|
||||
assertResult(mapper.findAiResourceFetchRows(orContext),
|
||||
"SELECT id,gmt_create,gmt_modified,name,type,c_desc,status,namespace_id,biz_tags,"
|
||||
+ "ext,c_from,version_info,meta_version,scope,owner,download_count "
|
||||
+ "FROM ai_resource WHERE namespace_id = ? AND ( status = ? OR type IN (?, ?) ) "
|
||||
+ "ORDER BY gmt_modified DESC LIMIT 7 OFFSET 3",
|
||||
namespaceId, "stable", "mcp", "a2a");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAiResourceVersionMapper() {
|
||||
AiResourceVersionMapperByPostgresql mapper = new AiResourceVersionMapperByPostgresql();
|
||||
assertEquals(DatabaseTypeConstant.POSTGRESQL, mapper.getDataSource());
|
||||
assertEquals("NOW()", mapper.getFunction("NOW()"));
|
||||
assertEquals(TableConstant.AI_RESOURCE_VERSION, mapper.getTableName());
|
||||
assertResult(mapper.findAiResourceVersionFetchRows(context),
|
||||
"SELECT id,gmt_create,gmt_modified,type,author,name,c_desc,status,version,namespace_id,"
|
||||
+ "storage,publish_pipeline_info,download_count FROM ai_resource_version "
|
||||
+ "WHERE namespace_id = ? AND name = ? AND type = ? AND status = ? "
|
||||
+ "AND version = ? ORDER BY gmt_modified DESC LIMIT 7 OFFSET 3",
|
||||
namespaceId, "nacos", "mcp", "stable", "1.0.0");
|
||||
|
||||
MapperContext minimalContext = new MapperContext(startRow, pageSize);
|
||||
minimalContext.putWhereParameter(FieldConstant.NAMESPACE_ID, namespaceId);
|
||||
minimalContext.putWhereParameter(FieldConstant.NAME, "nacos");
|
||||
minimalContext.putWhereParameter(FieldConstant.TYPE, "");
|
||||
minimalContext.putWhereParameter(FieldConstant.STATUS, "");
|
||||
minimalContext.putWhereParameter(FieldConstant.VERSION, "");
|
||||
assertResult(mapper.findAiResourceVersionFetchRows(minimalContext),
|
||||
"SELECT id,gmt_create,gmt_modified,type,author,name,c_desc,status,version,namespace_id,"
|
||||
+ "storage,publish_pipeline_info,download_count FROM ai_resource_version "
|
||||
+ "WHERE namespace_id = ? AND name = ? ORDER BY gmt_modified DESC LIMIT 7 OFFSET 3",
|
||||
namespaceId, "nacos");
|
||||
}
|
||||
|
||||
private static void assertResult(MapperResult result, String sql, Object... parameters) {
|
||||
assertEquals(normalizeSql(sql), normalizeSql(result.getSql()));
|
||||
assertArrayEquals(parameters, result.getParamList().toArray());
|
||||
}
|
||||
|
||||
private static String normalizeSql(String sql) {
|
||||
return sql.replaceAll("\\s+", " ").trim();
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class PostgresqlTenantMigrationScriptTest {
|
||||
|
||||
@Test
|
||||
void testMigrationScriptExistsAndCoversAllTenantTables() throws IOException {
|
||||
try (InputStream inputStream =
|
||||
getClass().getClassLoader()
|
||||
.getResourceAsStream("META-INF/pg-upgrade-null-tenant-id.sql")) {
|
||||
assertNotNull(inputStream);
|
||||
String sql = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
assertTrue(
|
||||
sql.contains("ALTER TABLE config_info ALTER COLUMN tenant_id SET DEFAULT ''"));
|
||||
assertTrue(
|
||||
sql.contains("ALTER TABLE config_info_gray ALTER COLUMN tenant_id SET DEFAULT ''"));
|
||||
assertTrue(sql.contains(
|
||||
"ALTER TABLE config_tags_relation ALTER COLUMN tenant_id SET DEFAULT ''"));
|
||||
assertTrue(
|
||||
sql.contains("ALTER TABLE his_config_info ALTER COLUMN tenant_id SET DEFAULT ''"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 1999-2026 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.datasource.impl.postgresql;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class PostgresqlTenantSchemaResourceTest {
|
||||
|
||||
@Test
|
||||
void testTenantColumnsAreHardenedInSchemaResource() throws IOException {
|
||||
try (InputStream inputStream =
|
||||
getClass().getClassLoader().getResourceAsStream("META-INF/pg-schema.sql")) {
|
||||
assertNotNull(inputStream);
|
||||
String schema = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
Matcher matcher = Pattern.compile("\"tenant_id\" varchar\\(128\\) NOT NULL DEFAULT ''")
|
||||
.matcher(schema);
|
||||
int count = 0;
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
assertEquals(4, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user