feat(postgresql): Added database user query function

This commit is contained in:
Sylphy
2025-04-22 13:43:47 +08:00
parent 9c82ed6fce
commit 3cefa0c4c7
9 changed files with 70 additions and 15 deletions

View File

@ -329,7 +329,7 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
if (resultSet.next()) { if (resultSet.next()) {
String nspname = resultSet.getString("nspname"); String nspname = resultSet.getString("nspname");
String relname = resultSet.getString("relname"); String relname = resultSet.getString("relname");
String typname = resultSet.getString("typname"); String typname = getConversionType(resultSet.getString("typname"));
String seqcache = resultSet.getString("seqcache"); String seqcache = resultSet.getString("seqcache");
String rolname = resultSet.getString("rolname"); String rolname = resultSet.getString("rolname");
String comment = resultSet.getString("comment"); String comment = resultSet.getString("comment");
@ -339,12 +339,6 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
String seqmin = resultSet.getString("seqmin"); String seqmin = resultSet.getString("seqmin");
Boolean seqcycle = resultSet.getBoolean("seqcycle"); Boolean seqcycle = resultSet.getBoolean("seqcycle");
switch (typname) {
case "int2" -> typname = "SMALLINT";
case "int8" -> typname = "BIGINT";
default -> typname = "INTEGER";
}
stringBuilder.append(CREATE_SEQUENCE).append(getMetaDataName(nspname, relname)).append(NEW_LINE); stringBuilder.append(CREATE_SEQUENCE).append(getMetaDataName(nspname, relname)).append(NEW_LINE);
if (Double.compare(databaseProductVersion, 10.0) >= 0) { if (Double.compare(databaseProductVersion, 10.0) >= 0) {
@ -406,7 +400,7 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
return Sequence.builder() return Sequence.builder()
.nspname(resultSet.getString("nspname")) .nspname(resultSet.getString("nspname"))
.relname(resultSet.getString("relname")) .relname(resultSet.getString("relname"))
.typname(resultSet.getString("typname")) .typname(getConversionType(resultSet.getString("typname")))
.seqcache(resultSet.getString("seqcache")) .seqcache(resultSet.getString("seqcache"))
.rolname(resultSet.getString("rolname")) .rolname(resultSet.getString("rolname"))
.comment(resultSet.getString("comment")) .comment(resultSet.getString("comment"))
@ -420,4 +414,25 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
return null; return null;
}); });
} }
@Override
public List<String> usernames(Connection connection) {
List<String> usernames = new ArrayList<>();
return SQLExecutor.getInstance().preExecute(connection, EXPORT_USERS_SQL, null, resultSet -> {
while (resultSet.next()) {
String username = resultSet.getString("username");
usernames.add(username);
}
return usernames;
});
}
private String getConversionType(String typname) {
switch (typname) {
case "int2" -> typname = "SMALLINT";
case "int8" -> typname = "BIGINT";
default -> typname = "INTEGER";
}
return typname;
}
} }

View File

@ -675,4 +675,10 @@ public class SQLConst {
pg_namespace n ON n.oid = c.relnamespace pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = ?; WHERE n.nspname = ?;
"""; """;
public static final String EXPORT_USERS_SQL = """
SELECT rolname AS username
FROM pg_roles
ORDER BY rolname;
""";
} }

View File

@ -98,4 +98,11 @@ public interface DatabaseService {
* @return * @return
*/ */
String exportDatabase(DatabaseExportParam param) throws SQLException; String exportDatabase(DatabaseExportParam param) throws SQLException;
/**
* Query the user under a database
*
* @return User list
*/
ListResult<String> getUsernameList();
} }

View File

@ -6,7 +6,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import ai.chat2db.server.domain.api.param.datasource.DatabaseCreateParam; import ai.chat2db.server.domain.api.param.datasource.DatabaseCreateParam;
import ai.chat2db.server.domain.api.param.datasource.DatabaseExportParam; import ai.chat2db.server.domain.api.param.datasource.DatabaseExportParam;
@ -196,4 +195,10 @@ public class DatabaseServiceImpl implements DatabaseService {
return "exportDatabase success"; return "exportDatabase success";
} }
@Override
public ListResult<String> getUsernameList(){
MetaData metaSchema = Chat2DBContext.getMetaData();
List<String> usernames = metaSchema.usernames(Chat2DBContext.getConnection());
return ListResult.of(usernames);
}
} }

View File

@ -45,7 +45,7 @@ public class SequenceServiceImpl implements SequenceService {
@Override @Override
public ListResult<Sql> buildSql(Sequence oldSequence, Sequence newSequence) { public ListResult<Sql> buildSql(Sequence oldSequence, Sequence newSequence) {
SqlBuilder sqlBuilder = Chat2DBContext.getSqlBuilder(); SqlBuilder<?> sqlBuilder = Chat2DBContext.getSqlBuilder();
List<Sql> sqls = new ArrayList<>(); List<Sql> sqls = new ArrayList<>();
if (ObjectUtil.isEmpty(oldSequence)) { if (ObjectUtil.isEmpty(oldSequence)) {
sqls.add(Sql.builder().sql(sqlBuilder.buildCreateSequenceSql(newSequence)).build()); sqls.add(Sql.builder().sql(sqlBuilder.buildCreateSequenceSql(newSequence)).build());

View File

@ -150,4 +150,14 @@ public class DatabaseController {
} }
return DataResult.of(task.getExportStatus()); return DataResult.of(task.getExportStatus());
} }
/**
* Query the database_user_list contained in the database
*
* @return username list
*/
@GetMapping("/database_username_list")
public ListResult<String> databaseUsernameList(@Valid DataSourceBaseRequest dataSourceBaseRequest) {
return databaseService.getUsernameList();
}
} }

View File

@ -292,4 +292,6 @@ public interface MetaData {
*/ */
Sequence sequences(Connection connection, @NotEmpty String databaseName, String schemaName, String sequenceName); Sequence sequences(Connection connection, @NotEmpty String databaseName, String schemaName, String sequenceName);
List<String> usernames(Connection connection);
} }

View File

@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils;
import java.sql.Connection; import java.sql.Connection;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -196,11 +197,16 @@ public class DefaultMetaService implements MetaData {
@Override @Override
public List<SimpleSequence> sequences(Connection connection, String databaseName, String schemaName){ public List<SimpleSequence> sequences(Connection connection, String databaseName, String schemaName){
return null; return Collections.emptyList();
} }
@Override @Override
public Sequence sequences(Connection connection, @NotEmpty String databaseName, String schemaName, String sequenceName){ public Sequence sequences(Connection connection, @NotEmpty String databaseName, String schemaName, String sequenceName){
return null; return null;
} }
@Override
public List<String> usernames(Connection connection){
return Collections.emptyList();
}
} }

View File

@ -14,7 +14,9 @@ import ai.chat2db.spi.model.*;
import ai.chat2db.spi.util.JdbcUtils; import ai.chat2db.spi.util.JdbcUtils;
import ai.chat2db.spi.util.ResultSetUtils; import ai.chat2db.spi.util.ResultSetUtils;
import ai.chat2db.spi.util.SqlUtils; import ai.chat2db.spi.util.SqlUtils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.TimeInterval; import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.druid.DbType; import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.SQLStatement;
@ -125,10 +127,12 @@ public class SQLExecutor implements CommandExecutor {
} }
public <R> R preExecute(Connection connection, String sql, String[] args, ResultSetFunction<R> function) { public <R> R preExecute(Connection connection, String sql, String[] args, ResultSetFunction<R> function) {
log.info("execute:{}", sql); log.info("preExecute:{}", sql);
try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
for (int i = 0; i < args.length; i++) { if (ArrayUtil.isNotEmpty(args)) {
preparedStatement.setObject(i + 1, args[i]); for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
} }
boolean query = preparedStatement.execute(); boolean query = preparedStatement.execute();
// Represents the query // Represents the query
@ -642,7 +646,7 @@ public class SQLExecutor implements CommandExecutor {
} }
return executeResult; return executeResult;
} }
/** /**
* Formats the given table name by stripping off any schema or catalog prefixes. * Formats the given table name by stripping off any schema or catalog prefixes.
* If the table name contains a dot ('.'), it splits the string by the dot * If the table name contains a dot ('.'), it splits the string by the dot