Skip to content
Open
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 @@ -31,6 +31,7 @@
import picocli.CommandLine;

import java.util.Collection;
import java.util.List;

@CommandLine.Command
public abstract class AbstractMetaObjectCommand extends CLIAbstractSubcommand {
Expand Down Expand Up @@ -129,6 +130,28 @@ private boolean containsObjectOfType(// in case if schema/database not specified
return false;
}

@Nullable
public DBSObjectContainer resolveContainerByPath(
@NotNull DBRProgressMonitor monitor,
@NotNull DBPDataSource dataSource,
@NotNull List<String> pathTokens
) throws DBException {
if (!(dataSource instanceof DBSObjectContainer container)) {
if (pathTokens.isEmpty()) {
return null;
}
throw new CLIException(
"Datasource '" + dataSource.getContainer().getName() + "' does not support nested objects",
CLIConstants.EXIT_CODE_ERROR
);
}
DBSObjectContainer current = container;
for (String token : pathTokens) {
current = getChildContainer(monitor, current, token);
}
return current;
}

@NotNull
protected DBSObjectContainer getChildContainer(
@NotNull DBRProgressMonitor monitor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 DBeaver Corp and others
*
* 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 org.dbvr.cli.sql.meta;

import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.cli.CLIConstants;
import org.jkiss.dbeaver.model.cli.CLIException;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.utils.CommonUtils;
import picocli.CommandLine;

import java.util.Arrays;
import java.util.List;

public class MetaFullNameOptions {

@Nullable
@CommandLine.Option(
names = {"--full-name", "-fn"},
description = "Fully qualified name (e.g. database.schema.table)"
)
protected String fullName;

public record Resolved(
boolean fromFullName,
@NotNull List<String> containerPath,
@Nullable String databaseName,
@Nullable String schemaName,
@Nullable String objectName
) {
@NotNull
public static Resolved fromExplicit(
@Nullable String databaseName,
@Nullable String schemaName,
@Nullable String objectName
) {
return new Resolved(false, List.of(), databaseName, schemaName, objectName);
}

@NotNull
public static Resolved fromTokens(@NotNull String[] tokens, boolean hasObject) {
if (!hasObject) {
return new Resolved(true, List.of(tokens), null, null, null);
}
// (table ddl -fn=db.schema.table → path=[db, schema], object=table).
String objectName = tokens[tokens.length - 1];
List<String> path = List.of(Arrays.copyOfRange(tokens, 0, tokens.length - 1));
return new Resolved(true, path, null, null, objectName);
}
}

public boolean isSpecified() {
return CommonUtils.isNotEmpty(fullName);
}

@NotNull
public Resolved resolve(
@NotNull DBPDataSource dataSource,
@Nullable String explicitDatabase,
@Nullable String explicitSchema,
@Nullable String explicitObject,
int maxContainerDepth,
boolean hasObject
) throws CLIException {
if (!isSpecified()) {
return Resolved.fromExplicit(explicitDatabase, explicitSchema, explicitObject);
}
rejectIfAnyExplicit(explicitDatabase, explicitSchema, explicitObject);
String[][] quoteStrings = dataSource.getSQLDialect().getIdentifierQuoteStrings();
return Resolved.fromTokens(splitAndValidate(maxContainerDepth, hasObject, quoteStrings), hasObject);
}

private static void rejectIfAnyExplicit(
@Nullable String database,
@Nullable String schema,
@Nullable String object
) throws CLIException {
if (CommonUtils.isNotEmpty(database) || CommonUtils.isNotEmpty(schema) || CommonUtils.isNotEmpty(object)) {
throw new CLIException(
"--full-name cannot be combined with --database-name, --schema-name or the object name option",
CLIConstants.EXIT_CODE_ILLEGAL_ARGUMENTS
);
}
}

@NotNull
private String[] splitAndValidate(
int maxContainerDepth,
boolean hasObject,
@Nullable String[][] quoteStrings
) throws CLIException {
String trimmed = fullName == null ? "" : fullName.trim();
if (trimmed.isEmpty()) {
throw new CLIException("Fully qualified name is empty", CLIConstants.EXIT_CODE_ILLEGAL_ARGUMENTS);
}
String[] tokens = SQLUtils.splitFullIdentifier(trimmed, ".", quoteStrings, false);
for (String token : tokens) {
if (token.isEmpty()) {
throw new CLIException("Invalid fully qualified name: '" + fullName + "'",
CLIConstants.EXIT_CODE_ILLEGAL_ARGUMENTS);
}
}
int maxParts = maxContainerDepth + (hasObject ? 1 : 0);
if (tokens.length > maxParts) {
throw new CLIException(
"Fully qualified name '" + fullName + "' has " + tokens.length
+ " parts but at most " + maxParts + " is allowed for this command",
CLIConstants.EXIT_CODE_ILLEGAL_ARGUMENTS
);
}
return tokens;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
protected abstract String getObjectTypeName();

@Nullable
protected abstract String getTargetObjectName();
protected abstract String getTargetObjectName(@NotNull DBPDataSource dataSource) throws DBException;

@Nullable
protected abstract DBSObjectContainer getBaseContainer(
Expand All @@ -63,10 +63,10 @@
}

protected void execute(@NotNull DBRProgressMonitor monitor) throws DBException {
AbstractMetaObjectCommand parent = getParentCommand();

Check warning on line 66 in bundles/org.dbvr.cli.sql/src/org/dbvr/cli/sql/meta/ddl/AbstractDDLCommand.java

View workflow job for this annotation

GitHub Actions / Check style / Lint

[checkstyle] reported by reviewdog 🐶 Distance between variable 'parent' declaration and its first usage is 4, but allowed 3. Consider making that variable final if you still need to store its value in advance (before method calls that might have side effects on the original value). Raw Output: /github/workspace/./bundles/org.dbvr.cli.sql/src/org/dbvr/cli/sql/meta/ddl/AbstractDDLCommand.java:66:9: warning: Distance between variable 'parent' declaration and its first usage is 4, but allowed 3. Consider making that variable final if you still need to store its value in advance (before method calls that might have side effects on the original value). (com.puppycrawl.tools.checkstyle.checks.coding.VariableDeclarationUsageDistanceCheck)
DBPDataSource dataSource = connectDataSource();
checkDDLSupported(monitor, dataSource);
String objectName = getTargetObjectName();
String objectName = getTargetObjectName(dataSource);
if (CommonUtils.isEmpty(objectName)) {
throw new CLIException(
getObjectTypeName() + " name is not specified",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class DatabaseDDLCommand extends AbstractDDLCommand {
@CommandLine.Mixin
private MetaDatabaseOptions containerOptions;

@CommandLine.Mixin
private MetaFullNameOptions fullNameOptions;

@NotNull
@Override
protected AbstractMetaObjectCommand getParentCommand() {
Expand All @@ -61,8 +64,15 @@ protected String getObjectTypeName() {

@Nullable
@Override
protected String getTargetObjectName() {
return containerOptions.getDatabaseName();
protected String getTargetObjectName(@NotNull DBPDataSource dataSource) throws DBException {
return fullNameOptions.resolve(
dataSource,
null,
null,
containerOptions.getDatabaseName(),
0,
true
).objectName();
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.dbvr.cli.sql.meta.ddl;

import org.dbvr.cli.sql.meta.AbstractMetaObjectCommand;
import org.dbvr.cli.sql.meta.MetaFullNameOptions;
import org.dbvr.cli.sql.meta.MetaSchemaOptions;
import org.dbvr.cli.sql.meta.SchemaCommand;
import org.jkiss.code.NotNull;
Expand All @@ -36,6 +37,26 @@ public class SchemaDDLCommand extends AbstractDDLCommand {
@CommandLine.Mixin
private MetaSchemaOptions containerOptions;

@CommandLine.Mixin
private MetaFullNameOptions fullNameOptions;

private MetaFullNameOptions.Resolved resolved;

@NotNull
private MetaFullNameOptions.Resolved resolved(@NotNull DBPDataSource dataSource) throws DBException {
if (resolved == null) {
resolved = fullNameOptions.resolve(
dataSource,
containerOptions.getDatabaseName(),
null,
containerOptions.getSchemaName(),
1,
true
);
}
return resolved;
}

@NotNull
@Override
protected AbstractMetaObjectCommand getParentCommand() {
Expand All @@ -50,8 +71,8 @@ protected String getObjectTypeName() {

@Nullable
@Override
protected String getTargetObjectName() {
return containerOptions.getSchemaName();
protected String getTargetObjectName(@NotNull DBPDataSource dataSource) throws DBException {
return resolved(dataSource).objectName();
}

@Nullable
Expand All @@ -60,6 +81,10 @@ protected DBSObjectContainer getBaseContainer(
@NotNull DBRProgressMonitor monitor,
@NotNull DBPDataSource dataSource
) throws DBException {
return parent.getBaseContainer(monitor, dataSource, containerOptions.getDatabaseName(), null);
MetaFullNameOptions.Resolved r = resolved(dataSource);
if (r.fromFullName()) {
return parent.resolveContainerByPath(monitor, dataSource, r.containerPath());
}
return parent.getBaseContainer(monitor, dataSource, r.databaseName(), null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.dbvr.cli.sql.meta.ddl;

import org.dbvr.cli.sql.meta.AbstractMetaObjectCommand;
import org.dbvr.cli.sql.meta.MetaFullNameOptions;
import org.dbvr.cli.sql.meta.MetaSchemaOptions;
import org.dbvr.cli.sql.meta.TableCommand;
import org.jkiss.code.NotNull;
Expand All @@ -36,10 +37,30 @@ public class TableDDLCommand extends AbstractDDLCommand {
@CommandLine.Mixin
private MetaSchemaOptions containerOptions;

@CommandLine.Mixin
private MetaFullNameOptions fullNameOptions;

@Nullable
@CommandLine.Option(names = {"--table-name", "-tn"}, description = "Table name")
protected String tableName;

private MetaFullNameOptions.Resolved resolved;

@NotNull
private MetaFullNameOptions.Resolved resolved(@NotNull DBPDataSource dataSource) throws DBException {
if (resolved == null) {
resolved = fullNameOptions.resolve(
dataSource,
containerOptions.getDatabaseName(),
containerOptions.getSchemaName(),
tableName,
2,
true
);
}
return resolved;
}

@NotNull
@Override
protected AbstractMetaObjectCommand getParentCommand() {
Expand All @@ -54,8 +75,8 @@ protected String getObjectTypeName() {

@Nullable
@Override
protected String getTargetObjectName() {
return tableName;
protected String getTargetObjectName(@NotNull DBPDataSource dataSource) throws DBException {
return resolved(dataSource).objectName();
}

@Nullable
Expand All @@ -64,6 +85,10 @@ protected DBSObjectContainer getBaseContainer(
@NotNull DBRProgressMonitor monitor,
@NotNull DBPDataSource dataSource
) throws DBException {
return parent.getBaseContainer(monitor, dataSource, containerOptions.getDatabaseName(), containerOptions.getSchemaName());
MetaFullNameOptions.Resolved r = resolved(dataSource);
if (r.fromFullName()) {
return parent.resolveContainerByPath(monitor, dataSource, r.containerPath());
}
return parent.getBaseContainer(monitor, dataSource, r.databaseName(), r.schemaName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.dbvr.cli.sql.meta.list;

import org.dbvr.cli.sql.meta.AbstractMetaObjectCommand;
import org.dbvr.cli.sql.meta.MetaFullNameOptions;
import org.dbvr.cli.sql.meta.MetaSchemaOptions;
import org.dbvr.cli.sql.meta.SchemaCommand;
import org.jkiss.code.NotNull;
Expand All @@ -36,6 +37,9 @@ public class SchemaListCommand extends AbstractListCommand {
@CommandLine.Mixin
private MetaSchemaOptions containerOptions;

@CommandLine.Mixin
private MetaFullNameOptions fullNameOptions;

@NotNull
@Override
protected AbstractMetaObjectCommand getParentCommand() {
Expand All @@ -54,6 +58,17 @@ protected DBSObjectContainer getBaseContainer(
@NotNull DBRProgressMonitor monitor,
@NotNull DBPDataSource dataSource
) throws DBException {
return parent.getBaseContainer(monitor, dataSource, containerOptions.getDatabaseName(), null);
MetaFullNameOptions.Resolved r = fullNameOptions.resolve(
dataSource,
containerOptions.getDatabaseName(),
null,
null,
1,
false
);
if (r.fromFullName()) {
return parent.resolveContainerByPath(monitor, dataSource, r.containerPath());
}
return parent.getBaseContainer(monitor, dataSource, r.databaseName(), null);
}
}
Loading
Loading