提交 3aa9e208 编写于 作者: S Serge Rider

#5384 Virtual FKs + dictionary reading + dictionary model refactoring


Former-commit-id: 8bd4bb7a
上级 657f1a3c
...@@ -21,10 +21,7 @@ import org.jkiss.code.Nullable; ...@@ -21,10 +21,7 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ModelPreferences; import org.jkiss.dbeaver.ModelPreferences;
import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBPSaveableObject;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.data.*; import org.jkiss.dbeaver.model.data.*;
import org.jkiss.dbeaver.model.exec.*; import org.jkiss.dbeaver.model.exec.*;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement; import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
...@@ -40,14 +37,23 @@ import org.jkiss.dbeaver.model.sql.SQLDataSource; ...@@ -40,14 +37,23 @@ import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.sql.SQLDialect; import org.jkiss.dbeaver.model.sql.SQLDialect;
import org.jkiss.dbeaver.model.sql.SQLUtils; import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.struct.*; import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.dbeaver.model.virtual.DBVEntity;
import org.jkiss.dbeaver.model.virtual.DBVUtils;
import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* JDBC abstract table implementation * JDBC abstract table implementation
*/ */
public abstract class JDBCTable<DATASOURCE extends DBPDataSource, CONTAINER extends DBSObject> public abstract class JDBCTable<DATASOURCE extends DBPDataSource, CONTAINER extends DBSObject>
extends AbstractTable<DATASOURCE, CONTAINER> extends AbstractTable<DATASOURCE, CONTAINER>
implements DBSDataManipulator, DBPSaveableObject implements DBSDictionary, DBSDataManipulator, DBPSaveableObject
{ {
private static final Log log = Log.getLog(JDBCTable.class); private static final Log log = Log.getLog(JDBCTable.class);
...@@ -534,6 +540,280 @@ public abstract class JDBCTable<DATASOURCE extends DBPDataSource, CONTAINER exte ...@@ -534,6 +540,280 @@ public abstract class JDBCTable<DATASOURCE extends DBPDataSource, CONTAINER exte
}; };
} }
////////////////////////////////////////////////////////////////////
// Dictionary
/**
* Enumerations supported only for unique constraints
* @return true for unique constraint else otherwise
*/
@Override
public boolean supportsDictionaryEnumeration() {
return true;
}
/**
* Returns prepared statements for enumeration fetch
* @param session execution context
* @param keyColumn enumeration column.
* @param keyPattern pattern for enumeration values. If null or empty then returns full enumration set
* @param preceedingKeys other constrain key values. May be null.
* @param sortByValue sort results by eky value. If false then sort by description
* @param sortAsc sort ascending/descending
* @param maxResults maximum enumeration values in result set @return @throws DBException
*/
@NotNull
@Override
public List<DBDLabelValuePair> getDictionaryEnumeration(
@NotNull DBCSession session,
@NotNull DBSEntityAttribute keyColumn,
Object keyPattern,
List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
boolean sortAsc,
int maxResults)
throws DBException
{
// Use default one
return readKeyEnumeration(
session,
keyColumn,
keyPattern,
preceedingKeys,
sortByValue,
sortAsc,
maxResults);
}
@NotNull
@Override
public List<DBDLabelValuePair> getDictionaryValues(@NotNull DBCSession session, @NotNull DBSEntityAttribute keyColumn, @NotNull List<Object> keyValues, List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc) throws DBException {
DBDValueHandler keyValueHandler = DBUtils.findValueHandler(session, keyColumn);
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(DBUtils.getQuotedIdentifier(keyColumn));
String descColumns = DBVUtils.getDictionaryDescriptionColumns(session.getProgressMonitor(), keyColumn);
if (descColumns != null) {
query.append(", ").append(descColumns);
}
query.append(" FROM ").append(DBUtils.getObjectFullName(this, DBPEvaluationContext.DML)).append(" WHERE ");
boolean hasCond = false;
// Preceeding keys
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue pk : preceedingKeys) {
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(getDataSource(), pk.getAttribute().getName())).append(" = ?");
hasCond = true;
}
}
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(keyColumn)).append(" IN (");
for (int i = 0; i < keyValues.size(); i++) {
if (i > 0) query.append(",");
query.append("?");
}
query.append(")");
query.append(" ORDER BY ");
if (sortByValue) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
} else {
// Sort by description
query.append(descColumns);
}
if (!sortAsc) {
query.append(" DESC");
}
try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, query.toString(), false, false, false)) {
int paramPos = 0;
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue precAttribute : preceedingKeys) {
DBDValueHandler precValueHandler = DBUtils.findValueHandler(session, precAttribute.getAttribute());
precValueHandler.bindValueObject(session, dbStat, precAttribute.getAttribute(), paramPos++, precAttribute.getValue());
}
}
for (Object value : keyValues) {
keyValueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, value);
}
dbStat.setLimit(0, keyValues.size());
if (dbStat.executeStatement()) {
try (DBCResultSet dbResult = dbStat.openResultSet()) {
return DBVUtils.readDictionaryRows(session, keyColumn, keyValueHandler, dbResult);
}
} else {
return Collections.emptyList();
}
}
}
private List<DBDLabelValuePair> readKeyEnumeration(
DBCSession session,
DBSEntityAttribute keyColumn,
Object keyPattern,
List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
boolean sortAsc,
int maxResults)
throws DBException
{
if (keyColumn.getParentObject() != this) {
throw new IllegalArgumentException("Bad key column argument");
}
DBDValueHandler keyValueHandler = DBUtils.findValueHandler(session, keyColumn);
if (keyPattern instanceof CharSequence && keyColumn.getDataKind() != DBPDataKind.NUMERIC) {
if (((CharSequence)keyPattern).length() > 0) {
keyPattern = "%" + keyPattern.toString() + "%";
} else {
keyPattern = null;
}
}
boolean searchInKeys = keyPattern != null;
if (keyPattern != null) {
if (keyColumn.getDataKind() == DBPDataKind.NUMERIC) {
if (keyPattern instanceof Number) {
// Subtract gap value to see some values before specified
int gapSize = maxResults / 2;
if (keyPattern instanceof Integer) {
keyPattern = (Integer) keyPattern - gapSize;
} else if (keyPattern instanceof Short) {
keyPattern = (Short) keyPattern - gapSize;
} else if (keyPattern instanceof Long) {
keyPattern = (Long) keyPattern - gapSize;
} else if (keyPattern instanceof Float) {
keyPattern = (Float) keyPattern - gapSize;
} else if (keyPattern instanceof Double) {
keyPattern = (Double) keyPattern - gapSize;
} else if (keyPattern instanceof BigInteger) {
keyPattern = ((BigInteger) keyPattern).subtract(BigInteger.valueOf(gapSize));
} else if (keyPattern instanceof BigDecimal) {
keyPattern = ((BigDecimal) keyPattern).subtract(new BigDecimal(gapSize));
} else {
searchInKeys = false;
}
} else if (keyPattern instanceof String) {
//searchInKeys = false;
// Ignore it
//keyPattern = Double.parseDouble((String) keyPattern) - gapSize;
}
} else if (keyPattern instanceof CharSequence && keyColumn.getDataKind() == DBPDataKind.STRING) {
// Its ok
} else {
searchInKeys = false;
}
}
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(DBUtils.getQuotedIdentifier(keyColumn));
String descColumns = DBVUtils.getDictionaryDescriptionColumns(session.getProgressMonitor(), keyColumn);
Collection<DBSEntityAttribute> descAttributes = null;
if (descColumns != null) {
descAttributes = DBVEntity.getDescriptionColumns(session.getProgressMonitor(), this, descColumns);
query.append(", ").append(descColumns);
}
query.append(" FROM ").append(DBUtils.getObjectFullName(this, DBPEvaluationContext.DML));
boolean searchInDesc = keyPattern instanceof CharSequence && descAttributes != null;
if (searchInDesc) {
boolean hasStringAttrs = false;
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
hasStringAttrs = true;
break;
}
}
if (!hasStringAttrs) {
searchInDesc = false;
}
}
if (!CommonUtils.isEmpty(preceedingKeys) || searchInKeys || searchInDesc) {
query.append(" WHERE ");
}
boolean hasCond = false;
// Preceeding keys
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (int i = 0; i < preceedingKeys.size(); i++) {
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(getDataSource(), preceedingKeys.get(i).getAttribute().getName())).append(" = ?");
hasCond = true;
}
}
if (keyPattern != null) {
if (hasCond) query.append(" AND (");
if (searchInKeys) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
if (keyColumn.getDataKind() == DBPDataKind.NUMERIC) {
query.append(" >= ?");
} else {
query.append(" LIKE ?");
}
}
}
// Add desc columns conditions
if (searchInDesc) {
boolean hasCondition = searchInKeys;
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
if (hasCondition) {
query.append(" OR ");
}
query.append(DBUtils.getQuotedIdentifier(descAttr)).append(" LIKE ?");
hasCondition = true;
}
}
}
if (hasCond) query.append(")");
query.append(" ORDER BY ");
if (sortByValue) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
} else {
// Sort by description
query.append(descColumns);
}
if (!sortAsc) {
query.append(" DESC");
}
try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, query.toString(), false, false, false)) {
int paramPos = 0;
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue precAttribute : preceedingKeys) {
DBDValueHandler precValueHandler = DBUtils.findValueHandler(session, precAttribute.getAttribute());
precValueHandler.bindValueObject(session, dbStat, precAttribute.getAttribute(), paramPos++, precAttribute.getValue());
}
}
if (keyPattern != null && searchInKeys) {
keyValueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, keyPattern);
}
if (searchInDesc) {
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
final DBDValueHandler valueHandler = DBUtils.findValueHandler(session, descAttr);
valueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, keyPattern);
}
}
}
dbStat.setLimit(0, maxResults);
if (dbStat.executeStatement()) {
try (DBCResultSet dbResult = dbStat.openResultSet()) {
return DBVUtils.readDictionaryRows(session, keyColumn, keyValueHandler, dbResult);
}
} else {
return Collections.emptyList();
}
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Truncate // Truncate
......
...@@ -18,41 +18,19 @@ package org.jkiss.dbeaver.model.impl.jdbc.struct; ...@@ -18,41 +18,19 @@ package org.jkiss.dbeaver.model.impl.jdbc.struct;
import org.jkiss.code.NotNull; import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable; import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBPSaveableObject; import org.jkiss.dbeaver.model.DBPSaveableObject;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.data.DBDAttributeValue;
import org.jkiss.dbeaver.model.data.DBDLabelValuePair;
import org.jkiss.dbeaver.model.data.DBDValueHandler;
import org.jkiss.dbeaver.model.exec.DBCResultSet;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.DBCStatement;
import org.jkiss.dbeaver.model.exec.DBCStatementType;
import org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer; import org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer;
import org.jkiss.dbeaver.model.impl.struct.AbstractTableConstraint; import org.jkiss.dbeaver.model.impl.struct.AbstractTableConstraint;
import org.jkiss.dbeaver.model.meta.Property; import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.struct.DBSConstraintEnumerable;
import org.jkiss.dbeaver.model.struct.DBSEntityAttribute;
import org.jkiss.dbeaver.model.struct.DBSEntityConstraint; import org.jkiss.dbeaver.model.struct.DBSEntityConstraint;
import org.jkiss.dbeaver.model.struct.DBSEntityConstraintType; import org.jkiss.dbeaver.model.struct.DBSEntityConstraintType;
import org.jkiss.dbeaver.model.virtual.DBVEntity;
import org.jkiss.dbeaver.model.virtual.DBVUtils;
import org.jkiss.utils.CommonUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* JDBC abstract constraint * JDBC abstract constraint
*/ */
public abstract class JDBCTableConstraint<TABLE extends JDBCTable> public abstract class JDBCTableConstraint<TABLE extends JDBCTable>
extends AbstractTableConstraint<TABLE> extends AbstractTableConstraint<TABLE>
implements DBSConstraintEnumerable, DBPSaveableObject implements DBPSaveableObject
{ {
private boolean persisted; private boolean persisted;
...@@ -87,277 +65,4 @@ public abstract class JDBCTableConstraint<TABLE extends JDBCTable> ...@@ -87,277 +65,4 @@ public abstract class JDBCTableConstraint<TABLE extends JDBCTable>
this.persisted = persisted; this.persisted = persisted;
} }
/**
* Enumerations supported only for unique constraints
* @return true for unique constraint else otherwise
*/
@Override
public boolean supportsEnumeration() {
return getConstraintType().isUnique();
}
/**
* Returns prepared statements for enumeration fetch
* @param session execution context
* @param keyColumn enumeration column.
* @param keyPattern pattern for enumeration values. If null or empty then returns full enumration set
* @param preceedingKeys other constrain key values. May be null.
* @param sortByValue sort results by eky value. If false then sort by description
* @param sortAsc sort ascending/descending
* @param maxResults maximum enumeration values in result set @return @throws DBException
*/
@Override
public List<DBDLabelValuePair> getKeyEnumeration(
DBCSession session,
DBSEntityAttribute keyColumn,
Object keyPattern,
List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
boolean sortAsc,
int maxResults)
throws DBException
{
// Use default one
return readKeyEnumeration(
session,
keyColumn,
keyPattern,
preceedingKeys,
sortByValue,
sortAsc,
maxResults);
}
@Override
public List<DBDLabelValuePair> getKeyEnumeration(DBCSession session, DBSEntityAttribute keyColumn, @NotNull List<Object> keyValues, List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc) throws DBException {
final TABLE table = getParentObject();
DBDValueHandler keyValueHandler = DBUtils.findValueHandler(session, keyColumn);
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(DBUtils.getQuotedIdentifier(keyColumn));
String descColumns = DBVUtils.getDictionaryDescriptionColumns(session.getProgressMonitor(), keyColumn);
if (descColumns != null) {
query.append(", ").append(descColumns);
}
query.append(" FROM ").append(DBUtils.getObjectFullName(table, DBPEvaluationContext.DML)).append(" WHERE ");
boolean hasCond = false;
// Preceeding keys
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue pk : preceedingKeys) {
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(getDataSource(), pk.getAttribute().getName())).append(" = ?");
hasCond = true;
}
}
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(keyColumn)).append(" IN (");
for (int i = 0; i < keyValues.size(); i++) {
if (i > 0) query.append(",");
query.append("?");
}
query.append(")");
query.append(" ORDER BY ");
if (sortByValue) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
} else {
// Sort by description
query.append(descColumns);
}
if (!sortAsc) {
query.append(" DESC");
}
try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, query.toString(), false, false, false)) {
int paramPos = 0;
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue precAttribute : preceedingKeys) {
DBDValueHandler precValueHandler = DBUtils.findValueHandler(session, precAttribute.getAttribute());
precValueHandler.bindValueObject(session, dbStat, precAttribute.getAttribute(), paramPos++, precAttribute.getValue());
}
}
for (Object value : keyValues) {
keyValueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, value);
}
dbStat.setLimit(0, keyValues.size());
if (dbStat.executeStatement()) {
try (DBCResultSet dbResult = dbStat.openResultSet()) {
return DBVUtils.readDictionaryRows(session, keyColumn, keyValueHandler, dbResult);
}
} else {
return Collections.emptyList();
}
}
}
private List<DBDLabelValuePair> readKeyEnumeration(
DBCSession session,
DBSEntityAttribute keyColumn,
Object keyPattern,
List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
boolean sortAsc,
int maxResults)
throws DBException
{
if (keyColumn.getParentObject() != this.getTable()) {
throw new IllegalArgumentException("Bad key column argument");
}
final TABLE table = getParentObject();
assert table != null;
DBDValueHandler keyValueHandler = DBUtils.findValueHandler(session, keyColumn);
if (keyPattern instanceof CharSequence && keyColumn.getDataKind() != DBPDataKind.NUMERIC) {
if (((CharSequence)keyPattern).length() > 0) {
keyPattern = "%" + keyPattern.toString() + "%";
} else {
keyPattern = null;
}
}
boolean searchInKeys = keyPattern != null;
if (keyPattern != null) {
if (keyColumn.getDataKind() == DBPDataKind.NUMERIC) {
if (keyPattern instanceof Number) {
// Subtract gap value to see some values before specified
int gapSize = maxResults / 2;
if (keyPattern instanceof Integer) {
keyPattern = (Integer) keyPattern - gapSize;
} else if (keyPattern instanceof Short) {
keyPattern = (Short) keyPattern - gapSize;
} else if (keyPattern instanceof Long) {
keyPattern = (Long) keyPattern - gapSize;
} else if (keyPattern instanceof Float) {
keyPattern = (Float) keyPattern - gapSize;
} else if (keyPattern instanceof Double) {
keyPattern = (Double) keyPattern - gapSize;
} else if (keyPattern instanceof BigInteger) {
keyPattern = ((BigInteger) keyPattern).subtract(BigInteger.valueOf(gapSize));
} else if (keyPattern instanceof BigDecimal) {
keyPattern = ((BigDecimal) keyPattern).subtract(new BigDecimal(gapSize));
} else {
searchInKeys = false;
}
} else if (keyPattern instanceof String) {
//searchInKeys = false;
// Ignore it
//keyPattern = Double.parseDouble((String) keyPattern) - gapSize;
}
} else if (keyPattern instanceof CharSequence && keyColumn.getDataKind() == DBPDataKind.STRING) {
// Its ok
} else {
searchInKeys = false;
}
}
StringBuilder query = new StringBuilder();
query.append("SELECT ").append(DBUtils.getQuotedIdentifier(keyColumn));
String descColumns = DBVUtils.getDictionaryDescriptionColumns(session.getProgressMonitor(), keyColumn);
Collection<DBSEntityAttribute> descAttributes = null;
if (descColumns != null) {
descAttributes = DBVEntity.getDescriptionColumns(session.getProgressMonitor(), table, descColumns);
query.append(", ").append(descColumns);
}
query.append(" FROM ").append(DBUtils.getObjectFullName(table, DBPEvaluationContext.DML));
boolean searchInDesc = keyPattern instanceof CharSequence && descAttributes != null;
if (searchInDesc) {
boolean hasStringAttrs = false;
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
hasStringAttrs = true;
break;
}
}
if (!hasStringAttrs) {
searchInDesc = false;
}
}
if (!CommonUtils.isEmpty(preceedingKeys) || searchInKeys || searchInDesc) {
query.append(" WHERE ");
}
boolean hasCond = false;
// Preceeding keys
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (int i = 0; i < preceedingKeys.size(); i++) {
if (hasCond) query.append(" AND ");
query.append(DBUtils.getQuotedIdentifier(getDataSource(), preceedingKeys.get(i).getAttribute().getName())).append(" = ?");
hasCond = true;
}
}
if (keyPattern != null) {
if (hasCond) query.append(" AND (");
if (searchInKeys) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
if (keyColumn.getDataKind() == DBPDataKind.NUMERIC) {
query.append(" >= ?");
} else {
query.append(" LIKE ?");
}
}
}
// Add desc columns conditions
if (searchInDesc) {
boolean hasCondition = searchInKeys;
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
if (hasCondition) {
query.append(" OR ");
}
query.append(DBUtils.getQuotedIdentifier(descAttr)).append(" LIKE ?");
hasCondition = true;
}
}
}
if (hasCond) query.append(")");
query.append(" ORDER BY ");
if (sortByValue) {
query.append(DBUtils.getQuotedIdentifier(keyColumn));
} else {
// Sort by description
query.append(descColumns);
}
if (!sortAsc) {
query.append(" DESC");
}
try (DBCStatement dbStat = session.prepareStatement(DBCStatementType.QUERY, query.toString(), false, false, false)) {
int paramPos = 0;
if (preceedingKeys != null && !preceedingKeys.isEmpty()) {
for (DBDAttributeValue precAttribute : preceedingKeys) {
DBDValueHandler precValueHandler = DBUtils.findValueHandler(session, precAttribute.getAttribute());
precValueHandler.bindValueObject(session, dbStat, precAttribute.getAttribute(), paramPos++, precAttribute.getValue());
}
}
if (keyPattern != null && searchInKeys) {
keyValueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, keyPattern);
}
if (searchInDesc) {
for (DBSEntityAttribute descAttr : descAttributes) {
if (descAttr.getDataKind() == DBPDataKind.STRING) {
final DBDValueHandler valueHandler = DBUtils.findValueHandler(session, descAttr);
valueHandler.bindValueObject(session, dbStat, keyColumn, paramPos++, keyPattern);
}
}
}
dbStat.setLimit(0, maxResults);
if (dbStat.executeStatement()) {
try (DBCResultSet dbResult = dbStat.openResultSet()) {
return DBVUtils.readDictionaryRows(session, keyColumn, keyValueHandler, dbResult);
}
} else {
return Collections.emptyList();
}
}
}
} }
...@@ -32,8 +32,10 @@ import org.jkiss.dbeaver.model.app.DBPPlatform; ...@@ -32,8 +32,10 @@ import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.app.DBPProject; import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.navigator.meta.DBXTreeFolder; import org.jkiss.dbeaver.model.navigator.meta.DBXTreeFolder;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSEntity;
import org.jkiss.dbeaver.model.struct.DBSObject; import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.DBSObjectState; import org.jkiss.dbeaver.model.struct.DBSObjectState;
import org.jkiss.dbeaver.model.virtual.DBVUtils;
import org.jkiss.dbeaver.runtime.DBWorkbench; import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.utils.RuntimeUtils; import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.ArrayUtils;
...@@ -191,6 +193,13 @@ public class DBNModel implements IResourceChangeListener { ...@@ -191,6 +193,13 @@ public class DBNModel implements IResourceChangeListener {
@Nullable @Nullable
public DBNDatabaseNode getNodeByObject(DBRProgressMonitor monitor, DBSObject object, boolean addFiltered) public DBNDatabaseNode getNodeByObject(DBRProgressMonitor monitor, DBSObject object, boolean addFiltered)
{ {
if (object instanceof DBSEntity) {
try {
object = DBVUtils.getRealEntity(monitor, (DBSEntity)object);
} catch (DBException e) {
log.debug("Error dereferencing virtual entity", e);
}
}
DBNDatabaseNode node = getNodeByObject(object); DBNDatabaseNode node = getNodeByObject(object);
if (node != null) { if (node != null) {
return node; return node;
......
/* /*
* DBeaver - Universal Database Manager * DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org) * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jkiss.dbeaver.model.struct; package org.jkiss.dbeaver.model.struct;
import org.jkiss.code.Nullable; import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException; import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.data.DBDAttributeValue; import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.data.DBDLabelValuePair; import org.jkiss.dbeaver.model.data.DBDAttributeValue;
import org.jkiss.dbeaver.model.exec.DBCSession; import org.jkiss.dbeaver.model.data.DBDLabelValuePair;
import org.jkiss.dbeaver.model.exec.DBCSession;
import java.util.List;
import java.util.List;
/**
* Enumerable Constraint. /**
* May return possible values for one of constraint's key. * Dictionary table (entity).
*/ * May return possible values for a set of attributes.
public interface DBSConstraintEnumerable extends DBSEntityConstraint */
{ public interface DBSDictionary
/** {
* Checks that this constrain supports key enumerations. /**
* Usually it depends on constraint type (enumerations makes sense only for unique constraints). * Checks that this constrain supports key enumerations.
* @return true or false * Usually it depends on constraint type (enumerations makes sense only for unique constraints).
*/ * @return true or false
boolean supportsEnumeration(); */
boolean supportsDictionaryEnumeration();
/**
* Gets enumeration values /**
* @param session * Gets enumeration values
* @param keyColumn enumeration column. * @param session session
* @param keyPattern pattern for enumeration values. If null or empty then returns full enumration set * @param keyColumn enumeration column.
* @param preceedingKeys other constrain key values. May be null. * @param keyPattern pattern for enumeration values. If null or empty then returns full enumration set
* @param sortByValue * @param preceedingKeys other constrain key values. May be null.
* @param sortAsc * @param sortByValue sort results by value
* @param maxResults maximum enumeration values in result set @return statement with result set which contains valid enumeration values. */ * @param sortAsc ascending sorting (irrelevant is @sortByValue is false)
List<DBDLabelValuePair> getKeyEnumeration( * @param maxResults maximum enumeration values in result set
DBCSession session, * @return statement with result set which contains valid enumeration values.
DBSEntityAttribute keyColumn, */
Object keyPattern, @NotNull
@Nullable List<DBDAttributeValue> preceedingKeys, List<DBDLabelValuePair> getDictionaryEnumeration(
boolean sortByValue, @NotNull DBCSession session,
boolean sortAsc, @NotNull DBSEntityAttribute keyColumn,
int maxResults) Object keyPattern,
throws DBException; @Nullable List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
List<DBDLabelValuePair> getKeyEnumeration( boolean sortAsc,
DBCSession session, int maxResults)
DBSEntityAttribute keyColumn, throws DBException;
List<Object> keyValues,
@Nullable List<DBDAttributeValue> preceedingKeys, @NotNull
boolean sortByValue, List<DBDLabelValuePair> getDictionaryValues(
boolean sortAsc) @NotNull DBCSession session,
throws DBException; @NotNull DBSEntityAttribute keyColumn,
@NotNull List<Object> keyValues,
@Nullable List<DBDAttributeValue> preceedingKeys,
boolean sortByValue,
boolean sortAsc)
throws DBException;
} }
\ No newline at end of file
...@@ -22,8 +22,11 @@ import org.jkiss.code.Nullable; ...@@ -22,8 +22,11 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.*; import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.data.DBDAttributeBinding; import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
import org.jkiss.dbeaver.model.data.DBDAttributeValue;
import org.jkiss.dbeaver.model.data.DBDLabelValuePair;
import org.jkiss.dbeaver.model.data.json.JSONUtils; import org.jkiss.dbeaver.model.data.json.JSONUtils;
import org.jkiss.dbeaver.model.exec.DBCLogicalOperator; import org.jkiss.dbeaver.model.exec.DBCLogicalOperator;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.*; import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.utils.CommonUtils; import org.jkiss.utils.CommonUtils;
...@@ -33,7 +36,7 @@ import java.util.*; ...@@ -33,7 +36,7 @@ import java.util.*;
/** /**
* Virtual entity descriptor * Virtual entity descriptor
*/ */
public class DBVEntity extends DBVObject implements DBSEntity, DBPQualifiedObject, IAdaptable { public class DBVEntity extends DBVObject implements DBSEntity, DBPQualifiedObject, DBSDictionary, IAdaptable {
private static final String[] DESC_COLUMN_PATTERNS = { private static final String[] DESC_COLUMN_PATTERNS = {
"title", "title",
...@@ -587,4 +590,26 @@ public class DBVEntity extends DBVObject implements DBSEntity, DBPQualifiedObjec ...@@ -587,4 +590,26 @@ public class DBVEntity extends DBVObject implements DBSEntity, DBPQualifiedObjec
return null; return null;
} }
@Override
public boolean supportsDictionaryEnumeration() {
return true;
}
@NotNull
@Override
public List<DBDLabelValuePair> getDictionaryEnumeration(@NotNull DBCSession session, @NotNull DBSEntityAttribute keyColumn, Object keyPattern, @Nullable List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc, int maxResults) throws DBException {
DBSEntity realEntity = getRealEntity(session.getProgressMonitor());
return realEntity instanceof DBSDictionary ?
((DBSDictionary) realEntity).getDictionaryEnumeration(session, keyColumn, keyPattern, preceedingKeys, sortByValue, sortAsc, maxResults) :
Collections.emptyList();
}
@NotNull
@Override
public List<DBDLabelValuePair> getDictionaryValues(@NotNull DBCSession session, @NotNull DBSEntityAttribute keyColumn, @NotNull List<Object> keyValues, @Nullable List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc) throws DBException {
DBSEntity realEntity = getRealEntity(session.getProgressMonitor());
return realEntity instanceof DBSDictionary ?
((DBSDictionary) realEntity).getDictionaryValues(session, keyColumn, keyValues, preceedingKeys, sortByValue, sortAsc) :
Collections.emptyList();
}
} }
...@@ -18,11 +18,7 @@ package org.jkiss.dbeaver.model.virtual; ...@@ -18,11 +18,7 @@ package org.jkiss.dbeaver.model.virtual;
import org.jkiss.code.NotNull; import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable; import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.data.DBDAttributeValue;
import org.jkiss.dbeaver.model.data.DBDLabelValuePair;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.*; import org.jkiss.dbeaver.model.struct.*;
...@@ -33,7 +29,7 @@ import java.util.List; ...@@ -33,7 +29,7 @@ import java.util.List;
/** /**
* Virtual constraint * Virtual constraint
*/ */
public class DBVEntityConstraint implements DBSEntityConstraint, DBSEntityReferrer, DBSConstraintEnumerable public class DBVEntityConstraint implements DBSEntityConstraint, DBSEntityReferrer
{ {
@NotNull @NotNull
private final DBVEntity entity; private final DBVEntity entity;
...@@ -143,22 +139,4 @@ public class DBVEntityConstraint implements DBSEntityConstraint, DBSEntityReferr ...@@ -143,22 +139,4 @@ public class DBVEntityConstraint implements DBSEntityConstraint, DBSEntityReferr
return null; return null;
} }
@Override
public boolean supportsEnumeration() {
return getEnumAttr() != null;
}
@Override
public List<DBDLabelValuePair> getKeyEnumeration(DBCSession session, DBSEntityAttribute keyColumn, Object keyPattern, @Nullable List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc, int maxResults) throws DBException {
DBSAttributeEnumerable enumAttr = getEnumAttr();
if (enumAttr == null) {
throw new DBException("Enumeration not supported");
}
return enumAttr.getValueEnumeration(session, keyPattern, maxResults);
}
@Override
public List<DBDLabelValuePair> getKeyEnumeration(DBCSession session, DBSEntityAttribute keyColumn, List<Object> keyValues, @Nullable List<DBDAttributeValue> preceedingKeys, boolean sortByValue, boolean sortAsc) throws DBException {
throw new DBException("Multi-key enumeration is not supported");
}
} }
...@@ -202,9 +202,9 @@ class GenericFilterValueEdit { ...@@ -202,9 +202,9 @@ class GenericFilterValueEdit {
} }
final DBSEntityAttribute fkAttribute = fkColumn.getAttribute(); final DBSEntityAttribute fkAttribute = fkColumn.getAttribute();
final DBSEntityConstraint refConstraint = association.getReferencedConstraint(); final DBSEntityConstraint refConstraint = association.getReferencedConstraint();
final DBSConstraintEnumerable enumConstraint = (DBSConstraintEnumerable) refConstraint; final DBSDictionary enumConstraint = (DBSDictionary) refConstraint.getParentObject();
if (fkAttribute != null && enumConstraint != null) { if (fkAttribute != null && enumConstraint != null) {
return enumConstraint.getKeyEnumeration( return enumConstraint.getDictionaryEnumeration(
session, session,
refColumn, refColumn,
filterPattern, filterPattern,
......
...@@ -107,10 +107,10 @@ public class ReferenceValueEditor { ...@@ -107,10 +107,10 @@ public class ReferenceValueEditor {
List<DBSEntityReferrer> refs = DBUtils.getAttributeReferrers(new VoidProgressMonitor(), entityAttribute, true); List<DBSEntityReferrer> refs = DBUtils.getAttributeReferrers(new VoidProgressMonitor(), entityAttribute, true);
DBSEntityReferrer constraint = refs.isEmpty() ? null : refs.get(0); DBSEntityReferrer constraint = refs.isEmpty() ? null : refs.get(0);
if (constraint instanceof DBSEntityAssociation && if (constraint instanceof DBSEntityAssociation &&
((DBSEntityAssociation)constraint).getReferencedConstraint() instanceof DBSConstraintEnumerable) ((DBSEntityAssociation)constraint).getAssociatedEntity() instanceof DBSDictionary)
{ {
final DBSConstraintEnumerable refConstraint = (DBSConstraintEnumerable) ((DBSEntityAssociation) constraint).getReferencedConstraint(); final DBSDictionary dictionary = (DBSDictionary) ((DBSEntityAssociation) constraint).getAssociatedEntity();
if (refConstraint != null && refConstraint.supportsEnumeration()) { if (dictionary != null && dictionary.supportsDictionaryEnumeration()) {
return constraint; return constraint;
} }
} }
...@@ -494,13 +494,13 @@ public class ReferenceValueEditor { ...@@ -494,13 +494,13 @@ public class ReferenceValueEditor {
} }
final DBSEntityAttribute fkAttribute = fkColumn.getAttribute(); final DBSEntityAttribute fkAttribute = fkColumn.getAttribute();
final DBSEntityConstraint refConstraint = association.getReferencedConstraint(); final DBSEntityConstraint refConstraint = association.getReferencedConstraint();
final DBSConstraintEnumerable enumConstraint = (DBSConstraintEnumerable) refConstraint; final DBSDictionary enumConstraint = (DBSDictionary) refConstraint.getParentObject();
if (fkAttribute != null && enumConstraint != null) { if (fkAttribute != null && enumConstraint != null) {
try (DBCSession session = valueController.getExecutionContext().openSession( try (DBCSession session = valueController.getExecutionContext().openSession(
monitor, monitor,
DBCExecutionPurpose.UTIL, DBCExecutionPurpose.UTIL,
NLS.bind(ResultSetMessages.dialog_value_view_context_name, fkAttribute.getName()))) { NLS.bind(ResultSetMessages.dialog_value_view_context_name, fkAttribute.getName()))) {
Collection<DBDLabelValuePair> enumValues = enumConstraint.getKeyEnumeration( Collection<DBDLabelValuePair> enumValues = enumConstraint.getDictionaryEnumeration(
session, session,
refColumn, refColumn,
pattern, pattern,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册