-
Notifications
You must be signed in to change notification settings - Fork 532
dbeaver/pro#8981 add api for reference panel in cloudbeaver #4313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devel
Are you sure you want to change the base?
Changes from all commits
6c95b65
1f7a913
7c62750
289781e
b09a60a
864a075
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,6 +72,17 @@ input SQLDataFilter { | |
| orderBy: String | ||
| } | ||
|
|
||
| type SQLResultColumnReference { | ||
| "Name of the association (foreign key) that connects this column to the target entity. For reverse references (isReference=true) this is the name of the association in the target entity that points back to this column)" | ||
| associationName: String! @since(version: "26.1.0") | ||
| "Fully qualified name of the entity the client will navigate to (referenced entity for forward FK, referencing entity for reverse reference)" | ||
| targetEntityName: String @since(version: "26.1.0") | ||
| "True if this is a reverse reference (another entity's FK points to this column); false for forward foreign keys" | ||
| isReference: Boolean! @since(version: "26.1.0") | ||
| "Navigator node path of the target entity, suitable for opening it directly in the UI. Null if the entity is not present in the navigator tree." | ||
| nodePath: String @since(version: "26.1.0") | ||
| } | ||
|
|
||
| type SQLResultColumn { | ||
| position: Int! | ||
| name: String | ||
|
|
@@ -96,6 +107,9 @@ type SQLResultColumn { | |
| "Operations supported for this attribute" | ||
| supportedOperations: [DataTypeLogicalOperation!]! | ||
|
|
||
| "Foreign key references for this column" | ||
| references: [SQLResultColumnReference!]! @since(version: "26.1.0") | ||
|
|
||
| "Description of the column" | ||
| description: String @since(version: "25.1.3") | ||
| } | ||
|
|
@@ -451,6 +465,19 @@ extend type Mutation { | |
| dataFormat: ResultDataFormat | ||
| ): AsyncTaskInfo! | ||
|
|
||
| "Creates async task for reading referenced data by foreign key cell. Set isReference=true to navigate a reverse reference (other entity's FK pointing to this row)." | ||
| asyncSqlNavigateForeignKey( | ||
| projectId: ID, | ||
| connectionId: ID!, | ||
| contextId: ID!, | ||
| resultsId: ID!, | ||
| columnIndex: Int!, | ||
| row: SQLResultRow!, | ||
| associationName: String, | ||
| dataFormat: ResultDataFormat, | ||
| isReference: Boolean @since(version: "26.1.0") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SInCE must be after func definition |
||
| ): AsyncTaskInfo! | ||
|
|
||
| "Returns transaction log info for the specified project, connection and context" | ||
| getTransactionLogInfo( | ||
| projectId: ID!, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /* | ||
| * DBeaver - Universal Database Manager | ||
| * Copyright (C) 2010-2024 DBeaver Corp and others | ||
| * 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. | ||
|
|
@@ -16,6 +16,10 @@ | |
| */ | ||
| package io.cloudbeaver.service.sql; | ||
|
|
||
| import io.cloudbeaver.model.session.WebSession; | ||
| import org.jkiss.code.NotNull; | ||
| import org.jkiss.code.Nullable; | ||
| import org.jkiss.dbeaver.DBException; | ||
| import org.jkiss.dbeaver.Log; | ||
| import org.jkiss.dbeaver.model.DBPDataKind; | ||
| import org.jkiss.dbeaver.model.DBPEvaluationContext; | ||
|
|
@@ -24,6 +28,13 @@ | |
| 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.runtime.DBRProgressMonitor; | ||
| import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor; | ||
| import org.jkiss.dbeaver.model.struct.*; | ||
| import org.jkiss.dbeaver.model.virtual.DBVUtils; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Web SQL query resultset. | ||
|
|
@@ -32,9 +43,12 @@ | |
|
|
||
| private static final Log log = Log.getLog(WebSQLQueryResultColumn.class); | ||
|
|
||
| @Nullable | ||
| private final WebSession session; | ||
| private final DBDAttributeBinding attrMeta; | ||
|
|
||
| public WebSQLQueryResultColumn(DBDAttributeBinding attrMeta) { | ||
| public WebSQLQueryResultColumn(@Nullable WebSession session, DBDAttributeBinding attrMeta) { | ||
|
Check warning on line 50 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java
|
||
| this.session = session; | ||
| this.attrMeta = attrMeta; | ||
| } | ||
|
|
||
|
|
@@ -130,8 +144,62 @@ | |
| return attrMeta.getValueHandler().getSupportedOperators(attrMeta); | ||
| } | ||
|
|
||
| @Property | ||
| public List<WebSQLQueryResultColumnReference> getReferences() { | ||
|
Check warning on line 148 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java
|
||
| List<WebSQLQueryResultColumnReference> references = new ArrayList<>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought we can get refs from model and here just convert into web beans |
||
|
|
||
| // Forward references: foreign keys where this column is the source | ||
| List<DBSEntityReferrer> referrers = attrMeta.getReferrers(); | ||
| if (referrers != null) { | ||
| for (DBSEntityReferrer referrer : referrers) { | ||
| if (referrer instanceof DBSEntityAssociation association) { | ||
| references.add(new WebSQLQueryResultColumnReference(session, association, false)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Reverse references: foreign keys from other entities targeting this column | ||
| DBSEntityAttribute entityAttribute = attrMeta.getEntityAttribute(); | ||
| if (entityAttribute != null) { | ||
| DBSEntity parentEntity = entityAttribute.getParentObject(); | ||
| DBRProgressMonitor monitor = session != null ? session.getProgressMonitor() : new VoidProgressMonitor(); | ||
| for (DBSEntityAssociation reverseRef : DBVUtils.getAllReferences(monitor, parentEntity)) { | ||
| try { | ||
| if (referenceTargetsAttribute(monitor, reverseRef, entityAttribute)) { | ||
| references.add(new WebSQLQueryResultColumnReference(session, reverseRef, true)); | ||
| } | ||
| } catch (DBException e) { | ||
| log.debug("Error reading attributes for reverse reference " + reverseRef.getName(), e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return references; | ||
| } | ||
|
|
||
| private boolean referenceTargetsAttribute( | ||
| @NotNull DBRProgressMonitor monitor, | ||
| @NotNull DBSEntityAssociation association, | ||
| @NotNull DBSEntityAttribute attribute | ||
| ) throws DBException { | ||
| DBSEntityConstraint refConstraint = association.getReferencedConstraint(); | ||
| if (!(refConstraint instanceof DBSEntityReferrer referrer)) { | ||
| return false; | ||
| } | ||
| List<? extends DBSEntityAttributeRef> attrs = referrer.getAttributeReferences(monitor); | ||
| if (attrs == null) { | ||
| return false; | ||
| } | ||
| for (DBSEntityAttributeRef ref : attrs) { | ||
| if (attribute.equals(ref.getAttribute())) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
|
Check warning on line 202 in server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/sql/WebSQLQueryResultColumn.java
|
||
| return attrMeta.getName(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| /* | ||
| * 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 io.cloudbeaver.model.session.WebSession; | ||
| import org.jkiss.code.NotNull; | ||
| import org.jkiss.code.Nullable; | ||
| import org.jkiss.dbeaver.DBException; | ||
| import org.jkiss.dbeaver.Log; | ||
| import org.jkiss.dbeaver.model.DBPEvaluationContext; | ||
| import org.jkiss.dbeaver.model.DBUtils; | ||
| import org.jkiss.dbeaver.model.meta.Property; | ||
| import org.jkiss.dbeaver.model.navigator.DBNNode; | ||
| 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 { | ||
|
|
||
| private static final Log log = Log.getLog(WebSQLQueryResultColumnReference.class); | ||
|
|
||
| @Nullable | ||
| private final WebSession session; | ||
| @NotNull | ||
| private final DBSEntityAssociation association; | ||
| private final boolean reverse; | ||
|
|
||
| public WebSQLQueryResultColumnReference( | ||
| @Nullable WebSession session, | ||
| @NotNull DBSEntityAssociation association, | ||
| boolean reverse | ||
| ) { | ||
| this.session = session; | ||
| this.association = association; | ||
| this.reverse = reverse; | ||
| } | ||
|
|
||
| @NotNull | ||
| @Property | ||
| public String getAssociationName() { | ||
| return association.getName(); | ||
| } | ||
|
|
||
| @Property | ||
| public boolean isReference() { | ||
| return reverse; | ||
| } | ||
|
|
||
| @Nullable | ||
| @Property | ||
| public String getTargetEntityName() { | ||
| DBSEntity targetEntity = getTargetEntity(); | ||
| if (targetEntity == null) { | ||
| return null; | ||
| } | ||
| return DBUtils.getObjectFullName(targetEntity, DBPEvaluationContext.UI); | ||
| } | ||
|
|
||
| @Nullable | ||
| @Property | ||
| public String getNodePath() { | ||
| if (session == null) { | ||
| return null; | ||
| } | ||
| DBSEntity targetEntity = getTargetEntity(); | ||
| if (targetEntity == null) { | ||
| return null; | ||
| } | ||
| try { | ||
| DBNNode node = session.getNavigatorModelOrThrow() | ||
| .getNodeByObject(session.getProgressMonitor(), targetEntity, false); | ||
| return node == null ? null : node.getNodeUri(); | ||
| } catch (DBException e) { | ||
| log.debug("Error resolving navigator node for entity " + targetEntity.getName(), e); | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| @Nullable | ||
| private DBSEntity getTargetEntity() { | ||
| if (reverse) { | ||
| return association.getParentObject(); | ||
| } | ||
| DBSEntityConstraint referencedConstraint = association.getReferencedConstraint(); | ||
| if (referencedConstraint == null) { | ||
| return null; | ||
| } | ||
| return referencedConstraint.getParentObject(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
26.1.1 everywhere