Align ClickHouse entity inspection pruning with DuckDB

This commit is contained in:
Intelli committed 2026-09-23 13:39:58 -06:00
1 parent 3af1079b51
commit 91f08590d0
5 files changed
+70 -4

No files matched your search

@@ -2,7 +2,7 @@ package net.coreprotect.database.clickhouse;
import java.util.regex.Pattern;
final class ClickHouseIdentifiers {
public final class ClickHouseIdentifiers {
private static final Pattern IDENTIFIER = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
@@ -21,7 +21,7 @@ final class ClickHouseIdentifiers {
return "`" + requireIdentifier(value, name) + "`";
}
static String qualified(String database, String table) {
public static String qualified(String database, String table) {
return quote(database, "ClickHouse database") + "." + quote(table, "ClickHouse table");
}
}
@@ -40,6 +40,11 @@ public final class ClickHouseJdbc implements AutoCloseable {
return dataSource.getConnection();
}
public static Connection openPatchConnection(ClickHouseJdbcConfig config) throws SQLException {
ClickHouseJdbcConfig patch = config.forPatches();
return new DataSourceImpl(patch.getJdbcUrl(), patch.getProperties()).getConnection();
}
Connection openAuxiliaryConnection() throws SQLException {
return auxiliaryDataSource.getConnection();
}
@@ -85,6 +85,12 @@ public final class ClickHouseJdbcConfig {
return config;
}
ClickHouseJdbcConfig forPatches() {
ClickHouseJdbcConfig config = new ClickHouseJdbcConfig(host, port, database, username, password, tls);
config.properties.setProperty("socket_timeout", "0");
return config;
}
public Properties getProperties() {
Properties copy = new Properties();
copy.putAll(properties);
@@ -27,11 +27,13 @@ public final class ClickHouseSchema {
+ "),toYYYYMM(toDateTime(time,'UTC')),0))";
private static final String EVENT_SORTING_KEY = "(family,wid,x,z,if(family IN ('database_lock','user','version'),0,time),rowid,if(family='"
+ BATCH_RECEIPT_FAMILY + "',toString(batch_id),''))";
private static final String[] ENTITY_SPAWN_INDEX = { "entity_spawn_rowid_idx", "entity_spawn_rowid", "bloom_filter(0.01)", "1" };
private static final String[][] EVENT_DATA_SKIPPING_INDEX_DEFINITIONS = {
{ "batch_sequence_idx", "batch_sequence", "minmax", "1" },
{ "rowid_idx", "rowid", "bloom_filter(0.01)", "1" },
{ "entity_uuid_idx", "uuid", "bloom_filter(0.01)", "1" },
{ "entity_kill_rowid_idx", "kill_rowid", "bloom_filter(0.01)", "1" }
{ "entity_kill_rowid_idx", "kill_rowid", "bloom_filter(0.01)", "1" },
ENTITY_SPAWN_INDEX
};
private static final String[][] STORAGE_METADATA_COLUMN_DEFINITIONS = {
{ "dataset_id", "UUID" + VALUE_CODEC },
@@ -283,6 +285,9 @@ public final class ClickHouseSchema {
statement.setString(3, expectedIndex[0]);
try (ResultSet resultSet = statement.executeQuery()) {
if (!resultSet.next()) {
if (ENTITY_SPAWN_INDEX[0].equals(expectedIndex[0])) {
continue;
}
throw new SQLException("ClickHouse table is missing required data-skipping index " + expectedIndex[0] + ": " + table);
}
boolean matches = normalizeSql(expectedIndex[2]).equals(normalizeSql(resultSet.getString(1)))
@@ -1,15 +1,65 @@
package net.coreprotect.patch.script;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Locale;
import net.coreprotect.config.Config;
import net.coreprotect.config.ConfigHandler;
import net.coreprotect.database.clickhouse.ClickHouseIdentifiers;
import net.coreprotect.database.clickhouse.ClickHouseJdbc;
import net.coreprotect.database.clickhouse.ClickHouseJdbcConfig;
import net.coreprotect.utility.ErrorReporter;
public class __2_25_1 {
protected static boolean patchClickHouse(Statement statement) {
return true;
try {
Config config = Config.getGlobal();
ClickHouseJdbcConfig jdbcConfig = new ClickHouseJdbcConfig(config.CLICKHOUSE_HOST, config.CLICKHOUSE_PORT,
config.CLICKHOUSE_DATABASE, config.CLICKHOUSE_USERNAME, config.CLICKHOUSE_PASSWORD, config.CLICKHOUSE_TLS);
try (Connection connection = ClickHouseJdbc.openPatchConnection(jdbcConfig)) {
upgradeEntityIndex(connection, config.CLICKHOUSE_DATABASE, ConfigHandler.prefix);
}
return true;
}
catch (Exception e) {
ErrorReporter.report(e);
return false;
}
}
private static void upgradeEntityIndex(Connection connection, String database, String prefix) throws SQLException {
String tableName = prefix + "event_data";
String table = ClickHouseIdentifiers.qualified(database, tableName);
try (Statement statement = connection.createStatement()) {
statement.execute("ALTER TABLE " + table + " ADD INDEX IF NOT EXISTS entity_spawn_rowid_idx entity_spawn_rowid TYPE bloom_filter(0.01) GRANULARITY 1");
String query = "SELECT type_full,expr,granularity FROM system.data_skipping_indices WHERE database=? AND table=? AND name=? LIMIT 2";
try (PreparedStatement indexStatement = connection.prepareStatement(query)) {
indexStatement.setString(1, database);
indexStatement.setString(2, tableName);
indexStatement.setString(3, "entity_spawn_rowid_idx");
try (ResultSet result = indexStatement.executeQuery()) {
if (!result.next()) {
throw new SQLException("ClickHouse entity inspection index is missing: " + tableName);
}
boolean matches = "bloom_filter(0.01)".equals(normalizeIndexDefinition(result.getString(1)))
&& "entity_spawn_rowid".equals(normalizeIndexDefinition(result.getString(2)))
&& result.getLong(3) == 1;
if (!matches || result.next()) {
throw new SQLException("ClickHouse entity inspection index has an incompatible definition: " + tableName);
}
}
}
statement.execute("ALTER TABLE " + table + " MATERIALIZE INDEX entity_spawn_rowid_idx SETTINGS mutations_sync=1");
}
}
private static String normalizeIndexDefinition(String value) {
return value == null ? "" : value.replaceAll("[\\s`]", "").toLowerCase(Locale.ROOT);
}
protected static boolean patchDuckDB(Statement statement) {