Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public String getCurrentSchema() throws SQLException {

@Override
public List<String> getSchemas() throws SQLException {
var result = this.execute(SQL.of("show databases"));
var result = this.execute(SQL.of("SELECT name FROM system.databases ORDER BY name"));
return result.getData().stream().map(row -> (String) row.get(0)).toList();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jumpserver.chen.modules.clickhouse;

import org.apache.commons.lang3.StringUtils;
import org.jumpserver.chen.framework.datasource.Datasource;
import org.jumpserver.chen.framework.datasource.base.BaseConnectionManager;
import org.jumpserver.chen.framework.datasource.entity.DBConnectInfo;
Expand Down Expand Up @@ -48,9 +49,17 @@ public String getDisplayJDBCUrl() {
return this.getConnectInfo().toDisplayJDBCUrl(jdbcUrlTemplate);
}

@Override
public String getDatabaseContextKey() {
// ClickHouse exposes databases through schema nodes, like MySQL/MariaDB.
return "schema";
}

@Override
public String getJDBCUrl(String database) {
return this.jdbcUrl;
if (StringUtils.isBlank(database)) {
return this.jdbcUrl;
}
return this.getConnectInfo().toJDBCUrl(jdbcUrlTemplate, database);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,8 @@ private static RelationScope relationScope(AgentRequestContext context, String r
StringUtils.defaultIfBlank(requestedSchema, context.schema())
));
String dialect = StringUtils.defaultString(context.dialect()).toLowerCase(Locale.ROOT);
if ("mysql".equals(dialect) || "mariadb".equals(dialect)) {
// MySQL/MariaDB providers query INFORMATION_SCHEMA by scope.schema(),
if ("mysql".equals(dialect) || "mariadb".equals(dialect) || "clickhouse".equals(dialect)) {
// MySQL/MariaDB/ClickHouse providers query metadata by scope.schema(),
// matching ResourceBrowser.resolveScope(catalog=null, schema=database).
return new RelationScope(null, schema != null ? schema : database);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public record TableMetadata(
List<ForeignKey> foreignKeys,
List<Index> indexes,
List<Constraint> constraints,
Statistics statistics,
String ddl
) {
public record Capabilities(
Expand All @@ -23,6 +24,9 @@ public record Capabilities(
boolean foreignKeys,
boolean indexes,
boolean constraints,
boolean statistics,
boolean estimatedRows,
boolean totalSizeBytes,
boolean ddl
) {
}
Expand All @@ -43,6 +47,9 @@ public record Column(
public record PrimaryKey(String name, List<String> columns) {
}

public record Statistics(Long estimatedRows, Long totalSizeBytes) {
}

public record ForeignKey(
String name,
List<String> columns,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jumpserver.chen.framework.datasource.metadata.ObjectRef;
import org.jumpserver.chen.framework.datasource.metadata.PrimaryKeyMetadata;
import org.jumpserver.chen.framework.datasource.metadata.RelationKind;
import org.jumpserver.chen.framework.datasource.metadata.RelationScope;
import org.jumpserver.chen.framework.i18n.MessageUtils;
import org.jumpserver.chen.framework.session.SessionManager;
import org.jumpserver.chen.web.entity.TableMetadata;
Expand All @@ -29,7 +30,7 @@
public class TableMetadataService {
private static final Set<String> DEFAULT_SECTIONS = Set.of("columns", "primaryKey");
private static final Set<String> AUDITED_PROPERTY_SECTIONS = Set.of(
"foreignKeys", "indexes", "constraints", "ddl"
"foreignKeys", "indexes", "constraints", "statistics", "ddl"
);

public TableMetadata getTableMetadata(TableMetadataRequest request) {
Expand Down Expand Up @@ -60,7 +61,11 @@ static boolean shouldAuditPropertyQuery(Set<String> sections, boolean force) {
TableMetadata load(MetadataCatalog catalog, ObjectRef ref, Set<String> sections, boolean force)
throws SQLException {
if (force) {
catalog.invalidate(ref);
if (sections.contains("statistics")) {
catalog.invalidate(new RelationScope(ref.catalog(), ref.schema()));
} else {
catalog.invalidate(ref);
}
}
return load(catalog, ref, sections);
}
Expand Down Expand Up @@ -88,12 +93,19 @@ TableMetadata load(MetadataCatalog catalog, ObjectRef ref, Set<String> sections)
var constraints = sections.contains("constraints")
? catalog.listConstraints(List.of(ref)).stream().map(this::toConstraint).toList()
: List.<TableMetadata.Constraint>of();
var statistics = sections.contains("statistics")
? catalog.listStatistics(new RelationScope(ref.catalog(), ref.schema())).stream()
.filter(item -> ref.equals(item.ref()))
.findFirst()
.map(item -> new TableMetadata.Statistics(item.estimatedRows(), item.totalSizeBytes()))
.orElse(null)
: null;
var ddl = sections.contains("ddl") ? catalog.getTableDefinition(ref) : null;

return new TableMetadata(
ref.catalog(), ref.schema(), ref.name(), ref.kind().code(),
toCapabilities(catalog.capabilities()), sections,
columns, primaryKey, foreignKeys, indexes, constraints, ddl
columns, primaryKey, foreignKeys, indexes, constraints, statistics, ddl
);
}

Expand Down Expand Up @@ -136,7 +148,8 @@ private TableMetadata.Constraint toConstraint(ConstraintMetadata constraint) {
private TableMetadata.Capabilities toCapabilities(MetadataCapabilities capabilities) {
return new TableMetadata.Capabilities(
capabilities.columns(), capabilities.primaryKeys(), capabilities.foreignKeys(),
capabilities.indexes(), capabilities.constraints(), capabilities.tableDefinitions()
capabilities.indexes(), capabilities.constraints(), capabilities.statistics(),
capabilities.tableRows(), capabilities.tableSize(), capabilities.tableDefinitions()
);
}

Expand All @@ -154,6 +167,7 @@ static Set<String> normalizeSections(Set<String> requested) {
case "foreignkeys", "foreignkey", "fk" -> "foreignKeys";
case "indexes", "indices" -> "indexes";
case "constraints" -> "constraints";
case "statistics", "stats" -> "statistics";
case "ddl" -> "ddl";
default -> throw new IllegalArgumentException(MessageUtils.getOrDefault(
"UnknownTableMetadataSection", "Unknown table metadata section: %s", section));
Expand Down