提交 7ea53c89 编写于 作者: S Serge Rider

#6745 PG data type resolution fixed. Virtual model: real model listener

上级 dc156e33
......@@ -188,10 +188,6 @@ public class DatabaseMappingAttribute implements DatabaseMappingObject {
return targetType;
}
// TODO: make some smart data type matcher
// Current solution looks like hack
String typeName = source.getTypeName();
DBPDataKind dataKind = source.getDataKind();
return DBStructUtils.mapTargetDataType(targetDataSource, source);
}
......
......@@ -325,12 +325,21 @@ class PostgreFDWConfigWizard extends BaseWizard implements DBPContextProvider {
pgTable.setForeignOptions(new String[0]);
for (DBSEntityAttribute attr : CommonUtils.safeCollection(entity.getAttributes(monitor))) {
// Cache data types
PostgreSchema catalogSchema = database.getCatalogSchema(monitor);
if (catalogSchema != null) {
catalogSchema.getDataTypes(monitor);
}
String defTypeName = DBStructUtils.mapTargetDataType(database, attr);
String plainTargetTypeName = SQLUtils.stripColumnTypeModifiers(defTypeName);
PostgreDataType dataType = database.getDataType(monitor, plainTargetTypeName);
if (dataType == null) {
log.error("Data type '" + plainTargetTypeName + "' not found. Skip column mapping.");
continue;
}
PostgreTableColumn newColumn = columnManager.createNewObject(monitor, commandContext, pgTable, null, options);
assert newColumn != null;
newColumn.setName(attr.getName());
String defTypeName = DBStructUtils.mapTargetDataType(database.getDataSource(), attr);
String plainTargetTypeName = SQLUtils.stripColumnTypeModifiers(defTypeName);
PostgreDataType dataType = database.getDataType(monitor, plainTargetTypeName);
newColumn.setDataType(dataType);
}
......
......@@ -863,10 +863,10 @@ public final class DBUtils {
}
@NotNull
public static String getDefaultDataTypeName(@NotNull DBPDataSource dataSource, DBPDataKind dataKind)
public static String getDefaultDataTypeName(@NotNull DBSObject objectContainer, DBPDataKind dataKind)
{
if (dataSource instanceof DBPDataTypeProvider) {
return ((DBPDataTypeProvider) dataSource).getDefaultDataTypeName(dataKind);
if (objectContainer instanceof DBPDataTypeProvider) {
return ((DBPDataTypeProvider) objectContainer).getDefaultDataTypeName(dataKind);
} else {
// Unsupported data kind
return "?";
......@@ -1303,25 +1303,32 @@ public final class DBUtils {
public static void fireObjectUpdate(@NotNull DBSObject object)
{
fireObjectUpdate(object, null);
fireObjectUpdate(object, null, null);
}
public static void fireObjectUpdate(DBSObject object, @Nullable Object data)
public static void fireObjectUpdate(DBSObject object, boolean enabled)
{
final DBPDataSourceContainer container = getContainer(object);
if (container != null) {
container.fireEvent(new DBPEvent(DBPEvent.Action.OBJECT_UPDATE, object, data));
container.fireEvent(new DBPEvent(DBPEvent.Action.OBJECT_UPDATE, object, enabled));
}
}
public static void fireObjectUpdate(DBSObject object, boolean enabled)
public static void fireObjectUpdate(DBSObject object, @Nullable Map<String, Object> options, @Nullable Object data)
{
final DBPDataSourceContainer container = getContainer(object);
if (container != null) {
container.fireEvent(new DBPEvent(DBPEvent.Action.OBJECT_UPDATE, object, enabled));
DBPEvent event = new DBPEvent(DBPEvent.Action.OBJECT_UPDATE, object, data);
event.setOptions(options);
container.fireEvent(event);
}
}
public static void fireObjectUpdate(DBSObject object, @Nullable Object data)
{
fireObjectUpdate(object, null, data);
}
public static void fireObjectAdd(DBSObject object, Map<String, Object> options)
{
final DBPDataSourceContainer container = getContainer(object);
......
......@@ -26,6 +26,9 @@ import org.jkiss.dbeaver.model.struct.DBSObject;
*/
public interface DBEObjectRenamer<OBJECT_TYPE extends DBSObject> extends DBEObjectManager<OBJECT_TYPE> {
String PROP_OLD_NAME = "oldName";
String PROP_NEW_NAME = "newName";
/**
* Describes object
*
......
......@@ -34,6 +34,7 @@ import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
......@@ -384,7 +385,12 @@ public abstract class SQLObjectEditor<OBJECT_TYPE extends DBSObject, CONTAINER_T
public void redoCommand(ObjectRenameCommand command) {
if (command.getObject() instanceof DBPNamedObject2) {
((DBPNamedObject2) command.getObject()).setName(command.newName);
DBUtils.fireObjectUpdate(command.getObject());
Map<String, Object> options = new LinkedHashMap<>();
options.put(DBEObjectRenamer.PROP_OLD_NAME, command.getOldName());
options.put(DBEObjectRenamer.PROP_NEW_NAME, command.getNewName());
DBUtils.fireObjectUpdate(command.getObject(), options, null);
}
}
......
......@@ -185,12 +185,12 @@ public final class DBStructUtils {
cyclicTables.addAll(realTables);
}
public static String mapTargetDataType(DBPDataSource targetDataSource, DBSTypedObject typedObject) {
public static String mapTargetDataType(DBSObject objectContainer, DBSTypedObject typedObject) {
String typeName = typedObject.getTypeName();
String typeNameLower = typeName.toLowerCase(Locale.ENGLISH);
DBPDataKind dataKind = typedObject.getDataKind();
if (targetDataSource instanceof DBPDataTypeProvider) {
DBPDataTypeProvider dataTypeProvider = (DBPDataTypeProvider) targetDataSource;
if (objectContainer instanceof DBPDataTypeProvider) {
DBPDataTypeProvider dataTypeProvider = (DBPDataTypeProvider) objectContainer;
DBSDataType dataType = dataTypeProvider.getLocalDataType(typeName);
if (dataType == null && typeNameLower.equals("double")) {
dataType = dataTypeProvider.getLocalDataType("DOUBLE PRECISION");
......@@ -245,7 +245,7 @@ public final class DBStructUtils {
}
}
if (targetType == null) {
typeName = DBUtils.getDefaultDataTypeName(targetDataSource, dataKind);
typeName = DBUtils.getDefaultDataTypeName(objectContainer, dataKind);
typeNameLower = typeName.toLowerCase(Locale.ENGLISH);
if (!possibleTypes.isEmpty()) {
targetType = possibleTypes.get(typeNameLower);
......@@ -264,9 +264,9 @@ public final class DBStructUtils {
}
// Get type modifiers from target datasource
if (targetDataSource instanceof SQLDataSource) {
SQLDialect dialect = ((SQLDataSource) targetDataSource).getSQLDialect();
String modifiers = dialect.getColumnTypeModifiers(targetDataSource, typedObject, typeName, dataKind);
if (objectContainer instanceof SQLDataSource) {
SQLDialect dialect = ((SQLDataSource) objectContainer).getSQLDialect();
String modifiers = dialect.getColumnTypeModifiers((SQLDataSource)objectContainer, typedObject, typeName, dataKind);
if (modifiers != null) {
typeName += modifiers;
}
......
......@@ -109,6 +109,10 @@ public class DBVEntityForeignKey implements DBSEntityConstraint, DBSEntityAssoci
return refEntityId;
}
public void setRefEntityId(String refEntityId) {
this.refEntityId = refEntityId;
}
public String getRefConstraintId() {
return refConstraintId;
}
......@@ -168,7 +172,8 @@ public class DBVEntityForeignKey implements DBSEntityConstraint, DBSEntityAssoci
@Override
public DBSEntity getAssociatedEntity() {
return getReferencedConstraint().getParentObject();
DBSEntityConstraint refC = getReferencedConstraint();
return refC == null ? null : refC.getParentObject();
}
@Override
......
......@@ -20,14 +20,14 @@ import com.google.gson.stream.JsonWriter;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.edit.DBEObjectRenamer;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
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.DBSObjectContainer;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.xml.SAXListener;
import org.jkiss.utils.xml.XMLBuilder;
......@@ -52,16 +52,14 @@ public class DBVModel extends DBVContainer {
}
public DBVModel(@NotNull DBPDataSourceContainer dataSourceContainer) {
super(null, "model");
super(null, dataSourceContainer.getId());
this.dataSourceContainer = dataSourceContainer;
this.id = dataSourceContainer.getId();
}
// Copy constructor
public DBVModel(@NotNull DBPDataSourceContainer dataSourceContainer, @NotNull DBVModel source) {
super(null, source.getId());
this.dataSourceContainer = dataSourceContainer;
this.id = dataSourceContainer.getId();
this(dataSourceContainer);
copyFrom(source);
}
......@@ -214,6 +212,21 @@ public class DBVModel extends DBVContainer {
}
}
private static void renameEntityInCache(String newRefEntityId, String oldName, String newName) {
String oldRefEntityId = newRefEntityId.replace("/" + newName, "/" + oldName);
synchronized (globalReferenceCache) {
List<DBVEntityForeignKey> fkList = globalReferenceCache.get(oldRefEntityId);
if (fkList != null) {
globalReferenceCache.remove(oldRefEntityId);
globalReferenceCache.put(newRefEntityId, fkList);
for (DBVEntityForeignKey fk : fkList) {
fk.setRefEntityId(newRefEntityId);
fk.getEntity().persistConfiguration();
}
}
}
}
public static void checkGlobalCacheIsEmpty() {
synchronized (globalReferenceCache) {
if (!globalReferenceCache.isEmpty()) {
......@@ -222,4 +235,27 @@ public class DBVModel extends DBVContainer {
}
}
public static class ModelChangeListener implements DBPEventListener {
@Override
public void handleDataSourceEvent(DBPEvent event) {
DBSObject object = event.getObject();
if (event.getAction() == DBPEvent.Action.OBJECT_UPDATE && object instanceof DBSEntity) {
// Handle table renames
Map<String, Object> options = event.getOptions();
if (options != null) {
String oldName = (String)options.get(DBEObjectRenamer.PROP_OLD_NAME);
String newName = (String)options.get(DBEObjectRenamer.PROP_NEW_NAME);
if (oldName != null && newName != null) {
DBNDatabaseNode objectNode = DBWorkbench.getPlatform().getNavigatorModel().getNodeByObject(object);
if (objectNode != null) {
String objectNodePath = objectNode.getNodeItemPath();
renameEntityInCache(objectNodePath, oldName, newName);
System.out.println("Handle rename " + oldName + " into " + newName);
}
}
}
}
}
}
}
......@@ -34,6 +34,7 @@ import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.struct.DBSObjectFilter;
import org.jkiss.dbeaver.model.virtual.DBVModel;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.runtime.resource.DBeaverNature;
......@@ -72,12 +73,16 @@ public class DataSourceRegistry implements DBPDataSourceRegistry {
private final List<DBWNetworkProfile> networkProfiles = new ArrayList<>();
private volatile boolean saveInProgress = false;
private final DBVModel.ModelChangeListener modelChangeListener = new DBVModel.ModelChangeListener();
public DataSourceRegistry(DBPPlatform platform, ProjectMetadata project) {
this.platform = platform;
this.project = project;
loadDataSources(false);
DataSourceProviderRegistry.getInstance().fireRegistryChange(this, true);
addDataSourceListener(modelChangeListener);
}
/**
......@@ -91,10 +96,13 @@ public class DataSourceRegistry implements DBPDataSourceRegistry {
dataSources.add(new DataSourceDescriptor(ds, this));
}
}
addDataSourceListener(modelChangeListener);
}
@Override
public void dispose() {
removeDataSourceListener(modelChangeListener);
DataSourceProviderRegistry.getInstance().fireRegistryChange(this, false);
synchronized (dataSourceListeners) {
if (!this.dataSourceListeners.isEmpty()) {
......
......@@ -781,11 +781,16 @@ public class EditForeignKeyPage extends BaseObjectEditPage {
if (curConstraint instanceof DBSEntityReferrer) {
// Read column nodes with void monitor because we already cached them above
for (DBSEntityAttributeRef pkColumn : ((DBSEntityReferrer)curConstraint).getAttributeReferences(monitor)) {
FKColumnInfo fkColumnInfo = new FKColumnInfo(pkColumn.getAttribute());
DBSEntityAttribute pkAttribute = pkColumn.getAttribute();
if (pkAttribute == null) {
log.debug("Constraint " + curConstraint.getName() + " column attribute not found");
continue;
}
FKColumnInfo fkColumnInfo = new FKColumnInfo(pkAttribute);
// Try to find matched column in own table
if (!CommonUtils.isEmpty(ownColumns)) {
for (DBSEntityAttribute ownColumn : ownColumns) {
if (ownColumn.getName().equals(pkColumn.getAttribute().getName()) && curEntity != pkColumn.getAttribute().getParentObject()) {
if (ownColumn.getName().equals(pkAttribute.getName()) && curEntity != pkAttribute.getParentObject()) {
fkColumnInfo.ownColumn = ownColumn;
break;
}
......@@ -799,9 +804,9 @@ public class EditForeignKeyPage extends BaseObjectEditPage {
item.setImage(0, getColumnIcon(fkColumnInfo.ownColumn));
item.setText(1, fkColumnInfo.ownColumn.getFullTypeName());
}
item.setText(2, pkColumn.getAttribute().getName());
item.setImage(2, getColumnIcon(pkColumn.getAttribute()));
item.setText(3, pkColumn.getAttribute().getFullTypeName());
item.setText(2, pkAttribute.getName());
item.setImage(2, getColumnIcon(pkAttribute));
item.setText(3, pkAttribute.getFullTypeName());
item.setData(fkColumnInfo);
}
} else if (enableCustomKeys && curRefTable != null) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册