mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
feat(gbase8s): support dropping a database from the tree
This commit is contained in:
@@ -52,6 +52,12 @@ public final class Gbase8sAgent extends ConfiguredJdbcAgent {
|
||||
private static final Pattern CREATE_DATABASE_LOCALE_DIRECTIVE = Pattern.compile(
|
||||
"^\\s*--\\s*DBX_DB_LOCALE\\s*=\\s*(\\S+)\\s*\\r?\\n(.*)$", Pattern.DOTALL);
|
||||
|
||||
// A bare `DROP DATABASE <name>` (unquoted identifier, optional trailing semicolon). The target
|
||||
// database's own locale is resolvable (it exists in sysdbslocale), so the drop is routed here
|
||||
// without a directive.
|
||||
private static final Pattern DROP_DATABASE_STATEMENT = Pattern.compile(
|
||||
"^\\s*DROP\\s+DATABASE\\s+([A-Za-z0-9_]+)\\s*;?\\s*$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public static final JdbcAgentProfile GBASE8S_PROFILE = new JdbcAgentProfile(
|
||||
"com.gbasedbt.jdbc.Driver",
|
||||
"jdbc:gbasedbt-sqli://{host}:{port}/{database}:GBASEDBTSERVER=gbase8s",
|
||||
@@ -181,9 +187,13 @@ public final class Gbase8sAgent extends ConfiguredJdbcAgent {
|
||||
return localized;
|
||||
}
|
||||
|
||||
private String resolveCollate(ConnectParams params, String database) {
|
||||
String key = params.getHost() + "|" + params.getPort() + "|" + getGbaseServer(params)
|
||||
private static String collateCacheKey(ConnectParams params, String database) {
|
||||
return params.getHost() + "|" + params.getPort() + "|" + getGbaseServer(params)
|
||||
+ "|" + database.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
private String resolveCollate(ConnectParams params, String database) {
|
||||
String key = collateCacheKey(params, database);
|
||||
String cached = collateByDatabase.get(key);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
@@ -270,7 +280,17 @@ public final class Gbase8sAgent extends ConfiguredJdbcAgent {
|
||||
public QueryResult executeQuery(String sql, String schema, ExecuteQueryOptions options) {
|
||||
CreateDatabaseLocaleDirective directive = parseCreateDatabaseLocaleDirective(sql);
|
||||
if (directive != null) {
|
||||
runCreateDatabaseWithLocale(directive.statement(), directive.locale());
|
||||
runDdlOnSysmasterWithLocale(directive.statement(), directive.locale());
|
||||
clearMetadataCache();
|
||||
return new QueryResult(Collections.emptyList(), Collections.emptyList(), 0, 0);
|
||||
}
|
||||
String dropTarget = parseDropDatabaseName(sql);
|
||||
if (dropTarget != null && databaseListParams != null) {
|
||||
// Informix cannot drop a database from a session whose DB_LOCALE differs, nor the
|
||||
// current database; run it from sysmaster pinned to the target database's own locale.
|
||||
String collate = resolveCollate(databaseListParams, dropTarget);
|
||||
runDdlOnSysmasterWithLocale("DROP DATABASE " + dropTarget, collate);
|
||||
invalidateCollateCache(dropTarget);
|
||||
clearMetadataCache();
|
||||
return new QueryResult(Collections.emptyList(), Collections.emptyList(), 0, 0);
|
||||
}
|
||||
@@ -281,6 +301,27 @@ public final class Gbase8sAgent extends ConfiguredJdbcAgent {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse {@code sql} as a bare {@code DROP DATABASE <name>} statement, returning the (unquoted)
|
||||
* target database name or {@code null} for anything else. Package visible so the routing
|
||||
* decision is testable without a live connection.
|
||||
*/
|
||||
static String parseDropDatabaseName(String sql) {
|
||||
if (sql == null) {
|
||||
return null;
|
||||
}
|
||||
Matcher drop = DROP_DATABASE_STATEMENT.matcher(sql);
|
||||
return drop.matches() ? drop.group(1) : null;
|
||||
}
|
||||
|
||||
private void invalidateCollateCache(String database) {
|
||||
ConnectParams base = databaseListParams;
|
||||
if (base == null) {
|
||||
return;
|
||||
}
|
||||
collateByDatabase.remove(collateCacheKey(base, database));
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code CREATE DATABASE} statement plus the DB_LOCALE carried by its leading directive
|
||||
* comment. Package visible so the routing decision is directly testable without a live
|
||||
@@ -307,12 +348,14 @@ public final class Gbase8sAgent extends ConfiguredJdbcAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a {@code CREATE DATABASE} statement on a sysmaster session whose {@code DB_LOCALE} is
|
||||
* pinned to {@code locale}, so the freshly created database inherits that codeset (Informix has
|
||||
* no charset clause in {@code CREATE DATABASE}). Falls back to the configured locale when
|
||||
* Run a DDL statement (e.g. {@code CREATE DATABASE} / {@code DROP DATABASE}) on a sysmaster
|
||||
* session whose {@code DB_LOCALE} is pinned to {@code locale}. Informix has no charset clause
|
||||
* in {@code CREATE DATABASE} (the new database inherits the creating session's DB_LOCALE) and
|
||||
* cannot drop a database from a session whose locale differs, or drop the current database —
|
||||
* so both run from sysmaster with the relevant locale. Falls back to the configured locale when
|
||||
* {@code locale} is blank or unsafe.
|
||||
*/
|
||||
private void runCreateDatabaseWithLocale(String statement, String locale) {
|
||||
private void runDdlOnSysmasterWithLocale(String statement, String locale) {
|
||||
ConnectParams base = databaseListParams;
|
||||
if (base == null) {
|
||||
throw new IllegalStateException("Not connected");
|
||||
|
||||
@@ -258,6 +258,17 @@ class Gbase8sAgentTest {
|
||||
Assertions.assertNull(Gbase8sAgent.parseCreateDatabaseLocaleDirective(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseDropDatabaseNameRecognizesBareDrop() {
|
||||
Assertions.assertEquals("app_db", Gbase8sAgent.parseDropDatabaseName("DROP DATABASE app_db;"));
|
||||
Assertions.assertEquals("app_db", Gbase8sAgent.parseDropDatabaseName(" drop database app_db "));
|
||||
Assertions.assertEquals("app_db", Gbase8sAgent.parseDropDatabaseName("Drop Database app_db"));
|
||||
Assertions.assertNull(Gbase8sAgent.parseDropDatabaseName("SELECT * FROM t;"));
|
||||
Assertions.assertNull(Gbase8sAgent.parseDropDatabaseName("CREATE DATABASE app_db;"));
|
||||
Assertions.assertNull(Gbase8sAgent.parseDropDatabaseName("DROP DATABASE \"app db\";"));
|
||||
Assertions.assertNull(Gbase8sAgent.parseDropDatabaseName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void omitsOwnerSchemasWhenTheDatabaseCannotUseThemInDml() {
|
||||
List<String> sql = new ArrayList<>();
|
||||
|
||||
@@ -3522,7 +3522,7 @@ const canSetCreateDatabaseLocale = computed(() => {
|
||||
|
||||
const canDropDatabase = computed(() => {
|
||||
const config = activeNode.value.connectionId ? connectionStore.getConfig(activeNode.value.connectionId) : undefined;
|
||||
return activeNode.value.type === "database" && !isSqlServerLinkedNode(activeNode.value) && supportsDatabaseCreation(config?.db_type);
|
||||
return activeNode.value.type === "database" && !isSqlServerLinkedNode(activeNode.value) && (supportsDatabaseCreation(config?.db_type) || supportsCreateDatabaseLocale(config?.db_type, config?.driver_profile));
|
||||
});
|
||||
|
||||
const databasePropertyGroups = computed(() => {
|
||||
|
||||
Reference in New Issue
Block a user