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
20 changes: 20 additions & 0 deletions server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ input SQLDataFilter {
orderBy: String
}

type SQLResultColumnReference {
associationName: String!
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use node path, client cant resolve name to the node path

targetEntityName: String
}

type SQLResultColumn {
position: Int!
name: String
Expand All @@ -96,6 +101,9 @@ type SQLResultColumn {
"Operations supported for this attribute"
supportedOperations: [DataTypeLogicalOperation!]!

"Foreign key references available for this column"
references: [SQLResultColumnReference!]!

"Description of the column"
description: String @since(version: "25.1.3")
}
Expand Down Expand Up @@ -451,6 +459,18 @@ extend type Mutation {
dataFormat: ResultDataFormat
): AsyncTaskInfo!

"Creates async task for reading referenced data by foreign key cell"
asyncSqlNavigateForeignKey(
projectId: ID,
connectionId: ID!,
contextId: ID!,
resultsId: ID!,
columnIndex: Int!,
row: SQLResultRow!,
associationName: String,
dataFormat: ResultDataFormat
): AsyncTaskInfo!

"Returns transaction log info for the specified project, connection and context"
getTransactionLogInfo(
projectId: ID!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@
@Nullable WebSQLDataFilter filter,
@Nullable WebDataFormat dataFormat) throws DBWebException;

@WebAction
WebAsyncTaskInfo asyncNavigateForeignKey(

Check warning on line 130 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/DBWServiceSQL.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Reference type 'WebAsyncTaskInfo' is missing a nullability annotation. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/DBWServiceSQL.java:130:5: warning: Reference type 'WebAsyncTaskInfo' is missing a nullability annotation. (sh.adelessfox.checkstyle.checks.NullabilityAnnotationsCheck)
@NotNull WebSession webSession,
@NotNull WebSQLContextInfo contextInfo,
@NotNull String resultsId,
@NotNull Integer columnIndex,
@NotNull WebSQLResultsRow row,
@Nullable String associationName,
@Nullable WebDataFormat dataFormat) throws DBException;

/**
* Reads dynamic trace from provided database results.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
import org.jkiss.dbeaver.model.exec.DBCLogicalOperator;
import org.jkiss.dbeaver.model.exec.DBExecUtils;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.struct.DBSEntityAssociation;
import org.jkiss.dbeaver.model.struct.DBSEntityReferrer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Web SQL query resultset.
Expand Down Expand Up @@ -130,8 +136,23 @@
return attrMeta.getValueHandler().getSupportedOperators(attrMeta);
}

@Property
public List<WebSQLQueryResultColumnReference> getReferences() {

Check warning on line 140 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Reference type 'List' is missing a nullability annotation. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java:140:12: warning: Reference type 'List' is missing a nullability annotation. (sh.adelessfox.checkstyle.checks.NullabilityAnnotationsCheck)
List<DBSEntityReferrer> referrers = attrMeta.getReferrers();
if (referrers == null || referrers.isEmpty()) {
return Collections.emptyList();
}
List<WebSQLQueryResultColumnReference> references = new ArrayList<>();
for (DBSEntityReferrer referrer : referrers) {
if (referrer instanceof DBSEntityAssociation) {
references.add(new WebSQLQueryResultColumnReference((DBSEntityAssociation) referrer));
}
}
return references;
}

@Override
public String toString() {

Check warning on line 155 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Reference type 'String' is missing a nullability annotation. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java:155:12: warning: Reference type 'String' is missing a nullability annotation. (sh.adelessfox.checkstyle.checks.NullabilityAnnotationsCheck)
return attrMeta.getName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 io.cloudbeaver.service.sql;

import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.struct.DBSEntity;
import org.jkiss.dbeaver.model.struct.DBSEntityAssociation;
import org.jkiss.dbeaver.model.struct.DBSEntityConstraint;

/**
* Web SQL query result column reference.
*/
public class WebSQLQueryResultColumnReference {

@NotNull
private final DBSEntityAssociation association;

public WebSQLQueryResultColumnReference(@NotNull DBSEntityAssociation association) {
this.association = association;
}

@NotNull
@Property
public String getAssociationName() {
return association.getName();
}

@Nullable
@Property
public String getTargetEntityName() {
DBSEntityConstraint referencedConstraint = association.getReferencedConstraint();
if (referencedConstraint == null) {
return null;
}
DBSEntity targetEntity = referencedConstraint.getParentObject();
if (targetEntity == null) {
return null;
}
return DBUtils.getObjectFullName(targetEntity, DBPEvaluationContext.UI);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,16 @@ public void bindWiring(DBWBindingContext model) throws DBWebException {
getDataFilter(env),
getDataFormat(env)
))
.dataFetcher("asyncSqlNavigateForeignKey", env ->
getService(env).asyncNavigateForeignKey(
getWebSession(env),
getSQLContext(env),
getArgumentVal(env, "resultsId"),
getArgumentVal(env, "columnIndex"),
new WebSQLResultsRow(getArgument(env, "row")),
getArgument(env, "associationName"),
getDataFormat(env)
))
.dataFetcher("asyncSqlExecuteResults", env ->
getService(env).asyncGetQueryResults(
getWebSession(env), getArgumentVal(env, "taskId")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
import org.jkiss.dbeaver.model.data.DBDReferenceNavigation;
import org.jkiss.dbeaver.model.data.DBDReferenceUtils;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCLogicalOperator;
import org.jkiss.dbeaver.model.exec.DBExecUtils;
Expand All @@ -59,9 +61,7 @@
import org.jkiss.dbeaver.model.sql.semantics.completion.SQLCompletionProposalComparator;
import org.jkiss.dbeaver.model.sql.semantics.completion.SQLQueryCompletionAnalyzer;
import org.jkiss.dbeaver.model.sql.semantics.completion.SQLQueryCompletionContext;
import org.jkiss.dbeaver.model.struct.DBSDataContainer;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.DBSWrapper;
import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
Expand Down Expand Up @@ -603,6 +603,85 @@
return contextInfo.getProcessor().getWebSession().createAndRunAsyncTask("Read data from container " + nodePath, runnable);
}

@Override
public WebAsyncTaskInfo asyncNavigateForeignKey(

Check warning on line 607 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Reference type 'WebAsyncTaskInfo' is missing a nullability annotation. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java:607:12: warning: Reference type 'WebAsyncTaskInfo' is missing a nullability annotation. (sh.adelessfox.checkstyle.checks.NullabilityAnnotationsCheck)
@NotNull WebSession webSession,
@NotNull WebSQLContextInfo contextInfo,
@NotNull String resultsId,
@NotNull Integer columnIndex,
@NotNull WebSQLResultsRow row,
@Nullable String associationName,
@Nullable WebDataFormat dataFormat
) {
WebAsyncTaskProcessor<String> runnable = new WebAsyncTaskProcessor<>() {
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException {

Check warning on line 618 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Reference type 'DBRProgressMonitor' is missing a nullability annotation. Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java:618:29: warning: Reference type 'DBRProgressMonitor' is missing a nullability annotation. (sh.adelessfox.checkstyle.checks.NullabilityAnnotationsCheck)
try {
monitor.beginTask("Navigate foreign key", 1);
//Get bindings
WebSQLResultsInfo resultsInfo = contextInfo.getResults(resultsId);
DBDAttributeBinding[] attributes = resultsInfo.getAttributes();
if (columnIndex < 0 || columnIndex >= attributes.length) {
throw new DBWebException("Column index '" + columnIndex + "' is out of range");
}
DBDAttributeBinding attribute = attributes[columnIndex];
// Get association
List<DBSEntityReferrer> referrers = attribute.getReferrers();
if (CommonUtils.isEmpty(referrers)) {
throw new DBException("Association not found in attribute [" + attribute.getName() + "]");
}
DBSEntityAssociation association = null;
for (DBSEntityReferrer referrer : referrers) {
if (referrer instanceof DBSEntityAssociation) {
DBSEntityAssociation referrerAssociation = (DBSEntityAssociation) referrer;
if (CommonUtils.isEmpty(associationName) ||
CommonUtils.equalObjects(associationName, referrerAssociation.getName())) {
association = referrerAssociation;
break;
}
}
}
if (association == null) {
if (CommonUtils.isEmpty(associationName)) {
throw new DBException("Association not found in attribute [" + attribute.getName() + "]");
}
throw new DBException("Association '" + associationName + "' not found in attribute [" + attribute.getName() + "]");
}

WebDBDResultSetDataProvider dataProvider = new WebDBDResultSetDataProvider(
resultsId,
contextInfo,
List.of(row)
);
DBDReferenceNavigation navigation = DBDReferenceUtils.resolveAssociationNavigation(
monitor,
dataProvider,
association,
dataProvider.getSelectedRows()
);
if (!(navigation.getTargetEntity() instanceof DBSDataContainer targetDataContainer)) {
throw new DBWebException("Referenced entity '" + navigation.getTargetEntity().getName() + "' is not a data container");

Check warning on line 663 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java

View workflow job for this annotation

GitHub Actions / Server / Lint

[checkstyle] reported by reviewdog 🐶 Line is longer than 140 characters (found 143). Raw Output: /github/workspace/./server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/impl/WebServiceSQL.java:663:0: warning: Line is longer than 140 characters (found 143). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
}
WebSQLExecuteInfo executeResults = contextInfo.getProcessor().readDataFromContainer(
contextInfo,
monitor,
targetDataContainer,
null,
WebSQLDataFilter.from(navigation.getTargetFilter()),
dataFormat
);
this.result = executeResults.getStatusMessage();
this.extendedResults = executeResults;
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
return webSession.createAndRunAsyncTask("Navigate foreign key from results " + resultsId, runnable);
}

@NotNull
@Override
public List<DBCTraceProperty> readDynamicTrace(
Expand Down
Loading