diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.ui/plugin.xml b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/plugin.xml
index 4ee0ae8c99351c4f47c03791e6e9ccdaf1913afe..849a150d56677bf89a02132240d4369478bafc5d 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql.ui/plugin.xml
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/plugin.xml
@@ -114,6 +114,10 @@
+
+
+
+
@@ -212,6 +216,24 @@
label="Disable trigger"
singleton="false">
+
+
+
+
+
+
{
+ @Override
+ public PostgreExtension configureObject(DBRProgressMonitor monitor, Object parent, PostgreExtension extension) {
+ return new UITask() {
+ @Override
+ protected PostgreExtension runTask() {
+ PostgreCreateExtensionDialog dialog = new PostgreCreateExtensionDialog(UIUtils.getActiveWorkbenchShell(), extension);
+ if (dialog.open() != IDialogConstants.OK_ID) {
+ return null;
+ }
+ extension.setName(dialog.getExtension().getName());
+ extension.setSchema(dialog.getSchema().getName());
+ return extension;
+ }
+ }.execute();
+ }
+
+}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/tools/maintenance/PostgreToolExtensionUninstall.java b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/tools/maintenance/PostgreToolExtensionUninstall.java
new file mode 100644
index 0000000000000000000000000000000000000000..554a5649e8b20e1ef81510e0a841611e5faee447
--- /dev/null
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/tools/maintenance/PostgreToolExtensionUninstall.java
@@ -0,0 +1,89 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
+ * Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
+ *
+ * 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.jkiss.dbeaver.ext.postgresql.tools.maintenance;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreObject;
+import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
+import org.jkiss.dbeaver.model.navigator.DBNUtils;
+import org.jkiss.dbeaver.model.struct.DBSObject;
+import org.jkiss.dbeaver.runtime.DBWorkbench;
+import org.jkiss.dbeaver.ui.UIUtils;
+import org.jkiss.dbeaver.ui.tools.IUserInterfaceTool;
+import org.jkiss.utils.CommonUtils;
+
+public class PostgreToolExtensionUninstall implements IUserInterfaceTool {
+
+ @Override
+ public void execute(IWorkbenchWindow window, IWorkbenchPart activePart, Collection objects)
+ throws DBException {
+ List extensionList = CommonUtils.filterCollection(objects, PostgreObject.class);
+ if (!extensionList.isEmpty()) {
+ SQLDialog dialog = new SQLDialog(activePart.getSite(), extensionList);
+ if (dialog.open() == IDialogConstants.OK_ID) {
+ refreshObjectsState(extensionList);
+ }
+ }
+
+ }
+ private void refreshObjectsState(List extList) {
+ try {
+ UIUtils.runInProgressDialog(monitor -> {
+ for (PostgreObject ext : extList) {
+ try {
+ DBNDatabaseNode extNode = DBNUtils.getNodeByObject(ext);
+ if (extNode != null) {
+ extNode.refreshNode(monitor, PostgreToolExtensionUninstall.this);
+ }
+ } catch (DBException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ DBWorkbench.getPlatformUI().showError("Refresh extensions state", "Error refreshign extension state", e.getTargetException());
+ }
+ }
+
+ class SQLDialog extends TableToolDialog {
+
+ public SQLDialog(IWorkbenchPartSite partSite, List exts) {
+ super(partSite, "Uninstall extension", exts);
+ }
+
+ @Override
+ protected void generateObjectCommand(List lines, PostgreObject object) {
+ lines.add("DROP EXTENSION " + ((PostgreObject) object).getName() + " CASCADE");
+ }
+
+ @Override
+ protected void createControls(Composite parent) {
+ createObjectsSelector(parent);
+ }
+ }
+}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/ui/PostgreCreateExtensionDialog.java b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/ui/PostgreCreateExtensionDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdc24c5dbb8f53723ed626c645fd84e4b1e20d0e
--- /dev/null
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql.ui/src/org/jkiss/dbeaver/ext/postgresql/ui/PostgreCreateExtensionDialog.java
@@ -0,0 +1,151 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
+ *
+ * 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.jkiss.dbeaver.ext.postgresql.ui;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.ext.postgresql.PostgreMessages;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension;
+import org.jkiss.dbeaver.model.runtime.AbstractJob;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+import org.jkiss.dbeaver.ui.UIUtils;
+import org.jkiss.dbeaver.ui.dialogs.BaseDialog;
+import org.jkiss.dbeaver.utils.GeneralUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * PostgreCreateExtensionDialog
+ */
+public class PostgreCreateExtensionDialog extends BaseDialog
+{
+ private PostgreAvailableExtension extension;
+ private final PostgreExtension newextension;
+ private List allSchemas;
+ private String name;
+ private PostgreSchema schema;
+ private List installed;
+
+ public PostgreCreateExtensionDialog(Shell parentShell, PostgreExtension extension) {
+ super(parentShell, PostgreMessages.dialog_create_extension_title, null);
+ this.newextension = extension;
+ }
+
+ private void checkEnabled() {
+ getButton(IDialogConstants.OK_ID).setEnabled(extension != null && schema != null);
+ }
+
+ @Override
+ protected Composite createDialogArea(Composite parent) {
+ final Composite composite = super.createDialogArea(parent);
+
+ final Composite group = new Composite(composite, SWT.NONE);
+ group.setLayout(new GridLayout(2, false));
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ final Text databaseText = UIUtils.createLabelText(group, "Database", newextension.getDatabase().getName(), SWT.BORDER | SWT.READ_ONLY); //$NON-NLS-2$
+
+ final Combo extensionCombo = UIUtils.createLabelCombo(group, PostgreMessages.dialog_create_extension_name, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
+ final Combo schemaCombo = UIUtils.createLabelCombo(group, PostgreMessages.dialog_create_extension_schema, SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY);
+
+ schemaCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ schema = allSchemas.get(schemaCombo.getSelectionIndex());
+ checkEnabled();
+ }
+ });
+
+ extensionCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ extension = installed.get(extensionCombo.getSelectionIndex());
+ extensionCombo.setToolTipText(installed.get(extensionCombo.getSelectionIndex()).getDescription());
+ checkEnabled();
+ }
+ });
+
+ new AbstractJob("Load schemas") {
+
+ @Override
+ protected IStatus run(DBRProgressMonitor monitor) {
+ try {
+ allSchemas = new ArrayList<>(newextension.getDatabase().getSchemas(monitor));
+ UIUtils.syncExec(() -> {
+ for (PostgreSchema schema : allSchemas) {
+ schemaCombo.add(schema.getName());
+ }
+ });
+ } catch (DBException e) {
+ return GeneralUtils.makeExceptionStatus(e);
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+
+ new AbstractJob("Load available extensions") {
+
+ @Override
+ protected IStatus run(DBRProgressMonitor monitor) {
+ try {
+ installed = new ArrayList<>(newextension.getDatabase().getAvailableExtensions(monitor));
+ UIUtils.syncExec(() -> {
+ for (PostgreAvailableExtension e : installed) {
+ extensionCombo.add(e.getName());
+ }
+ });
+ } catch (DBException e) {
+ return GeneralUtils.makeExceptionStatus(e);
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent)
+ {
+ super.createButtonsForButtonBar(parent);
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ }
+
+ public PostgreAvailableExtension getExtension() {
+ return extension;
+ }
+
+ public PostgreSchema getSchema() {
+ return schema;
+ }
+
+
+}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle.properties b/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle.properties
index 87de67455ed32e72e9b6e3077e92c4194d7f74c1..d9852fcf559487538bf64623d0f71a2acee47301 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle.properties
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle.properties
@@ -178,11 +178,25 @@ meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase.name.description=
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase.template.name=Template
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase.template.description=
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.name.name=Name
-meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.name.description=
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.name.description=Extension name
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.schema.name=Schema
-meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.schema.description=
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.schema.description=Installed schema
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.version.name=Version
-meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.version.description=
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.version.description=Installed version
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.relocatable.name=Relocatable
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.relocatable.description=Can be relocated
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.tables.name=Tables
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.tables.description=Using tables
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.conditions.name=Conditions
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.conditions.description=ExtensionConditions
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.name.name=Name
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.name.description=Extension name
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.version.name=Version
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.version.description=Extension version
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.installedVersion.name=Installed
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.installedVersion.description=Installed version
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.description.name=Description
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.description.description=Comment
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAggregate.name.name=Name
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAggregate.name.description=Aggregate function name
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAggregate.inputTypes.name=Inputs
@@ -576,8 +590,10 @@ tree.database.node.name=Database
tree.databases.node.name=Databases
tree.encoding.node.name=Encoding
tree.encodings.node.name=Encodings
-tree.extension.node.name=Extension
-tree.extensions.node.name=Extensions
+tree.extension.node.name=Installed Extension
+tree.extensions.node.name=Installed Extensions
+tree.avalextension.node.name=Available Extension
+tree.avalextensions.node.name=Available Extensions
tree.foreignDataWrapper.node.name=Foreign data wrapper
tree.foreignDataWrappers.node.name=Foreign data wrappers
tree.foreignServer.node.name=Foreign server
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle_ru.properties b/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle_ru.properties
index 95c77bf7db87ec73fca47e929a968d3e1f576cb2..c451aa17a80b78ed20863362bbce8792d90bb833 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle_ru.properties
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/OSGI-INF/l10n/bundle_ru.properties
@@ -174,6 +174,20 @@ meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.schema.name=\u0421\
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.schema.description=
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.version.name=\u0412\u0435\u0440\u0441\u0438\u044F
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.version.description=
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.relocatable.name=\u041F\u0435\u0440\u0435\u043C\u0435\u0449\u0430\u0435\u043C\u043E\u0435
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.relocatable.description=\u041C\u043E\u0436\u043D\u043E \u043F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C \u0432 \u0434\u0440\u0443\u0433\u0443\u044E \u0441\u0445\u0435\u043C\u0443
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.tables.name=\u0422\u0430\u0431\u043B\u0438\u0446\u044B
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.tables.description=\u0442\u0430\u0431\u043B\u0438\u0446\u044B \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.conditions.name=\u0423\u0441\u043B\u043E\u0432\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension.conditions.description=\u0444\u0438\u043B\u044C\u0442\u0440\u0430 WHERE \u0434\u043B\u044F \u0442\u0430\u0431\u043B\u0438\u0446 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.name.name=\u0418\u043C\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.name.description=\u0418\u043C\u044F \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.version.name=\u0412\u0435\u0440\u0441\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.version.description=\u0412\u0435\u0440\u0441\u0438\u044F \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.installedVersion.name=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.installedVersion.description=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.description.name=\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435
+meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreAvailableExtension.description.description=\u041A\u0440\u0430\u0442\u043A\u043E\u0435 \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreForeignDataWrapper.handler.name=\u0424\u0443\u043D\u043A\u0446\u0438\u044F \u0443\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044F
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreForeignDataWrapper.handler.description=\u0424\u0443\u043D\u043A\u0446\u0438\u044F \u0443\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044F
meta.org.jkiss.dbeaver.ext.postgresql.model.PostgreForeignDataWrapper.name.name=\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435
@@ -493,8 +507,10 @@ tree.database.node.name=\u0411\u0430\u0437\u0430 \u0434\u0430\u043D\u043D\u044B\
tree.databases.node.name=\u0411\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445
tree.encoding.node.name=\u041A\u043E\u0434\u0438\u0440\u043E\u0432\u043A\u0430
tree.encodings.node.name=\u041A\u043E\u0434\u0438\u0440\u043E\u0432\u043A\u0438
-tree.extension.node.name=\u041C\u043E\u0434\u0443\u043B\u044C \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
-tree.extensions.node.name=\u041C\u043E\u0434\u0443\u043B\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+tree.extension.node.name=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+tree.extensions.node.name=\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+tree.avalextension.node.name=\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
+tree.avalextensions.node.name=\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u044F
tree.extensions.node.tip=\u0421\u043F\u0438\u0441\u043E\u043A \u0438\u043C\u0435\u043D \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0439
tree.foreignDataWrapper.node.name=\u041E\u0431\u043E\u043B\u043E\u0447\u043A\u0430 \u0432\u043D\u0435\u0448\u043D\u0438\u0445 \u0434\u0430\u043D\u043D\u044B\u0445
tree.foreignDataWrappers.node.name=\u041E\u0431\u043E\u043B\u043E\u0447\u043A\u0438 \u0432\u043D\u0435\u0448\u043D\u0438\u0445 \u0434\u0430\u043D\u043D\u044B\u0445
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/plugin.xml b/plugins/org.jkiss.dbeaver.ext.postgresql/plugin.xml
index d6ee3d157cd3dd4caa9efafc87fc7637cd939831..7b1132ab3031ad1fef908d181328823d23856b0d 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/plugin.xml
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/plugin.xml
@@ -160,11 +160,6 @@
-
-
-
-
-
@@ -220,6 +215,9 @@
+
+
+
@@ -447,6 +445,7 @@
+
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/edit/PostgreExtensionManager.java b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/edit/PostgreExtensionManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e4093dc794dbfe9ebee36d47b23b4d628d8fc6f
--- /dev/null
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/edit/PostgreExtensionManager.java
@@ -0,0 +1,92 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
+ * Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
+ *
+ * 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.jkiss.dbeaver.ext.postgresql.edit;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreDatabase;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreExtension;
+import org.jkiss.dbeaver.model.DBPDataSource;
+import org.jkiss.dbeaver.model.DBUtils;
+import org.jkiss.dbeaver.model.edit.DBECommandContext;
+import org.jkiss.dbeaver.model.edit.DBEPersistAction;
+import org.jkiss.dbeaver.model.impl.DBSObjectCache;
+import org.jkiss.dbeaver.model.impl.edit.SQLDatabasePersistAction;
+import org.jkiss.dbeaver.model.impl.sql.edit.SQLObjectEditor;
+import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
+
+public class PostgreExtensionManager extends SQLObjectEditor{
+
+ @Override
+ public long getMakerOptions(DBPDataSource dataSource) {
+ return FEATURE_SAVE_IMMEDIATELY;
+ }
+
+ @Override
+ public DBSObjectCache getObjectsCache(PostgreExtension object) {
+ return object.getDatabase().extensionCache;
+ }
+
+ @Override
+ protected PostgreExtension createDatabaseObject(DBRProgressMonitor monitor, DBECommandContext context,
+ Object container, Object copyFrom, Map options) throws DBException {
+ return new PostgreExtension((PostgreDatabase) container);
+ }
+
+
+ @Override
+ protected void addObjectCreateActions(DBRProgressMonitor monitor, List actions,
+ SQLObjectEditor.ObjectCreateCommand command,
+ Map options) {
+ final PostgreExtension extension = command.getObject();
+ final StringBuilder script = new StringBuilder("CREATE EXTENSION " + DBUtils.getQuotedIdentifier(extension));
+ script.append(" SCHEMA ").append(extension.getSchema());
+
+ actions.add(
+ new SQLDatabasePersistAction("Create extension", script.toString()) //$NON-NLS-2$
+ );
+ }
+
+ @Override
+ protected void addObjectDeleteActions(List actions,
+ SQLObjectEditor.ObjectDeleteCommand command,
+ Map options) {
+ }
+
+ @Override
+ public boolean canCreateObject(Object container) {
+ return true;
+ }
+
+ @Override
+ public boolean canDeleteObject(PostgreExtension object) {
+ return false;
+ }
+
+ @Override
+ public boolean canEditObject(PostgreExtension object) {
+ return false;
+ }
+
+
+
+
+}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreAvailableExtension.java b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreAvailableExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..daec0903e6d929c82cdcddc7bb583f4eaa1dcb1b
--- /dev/null
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreAvailableExtension.java
@@ -0,0 +1,101 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
+ * Copyright (C) 2019 Andrew Khitrin (ahitrin@gmail.com)
+ *
+ * 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.jkiss.dbeaver.ext.postgresql.model;
+
+import java.sql.ResultSet;
+import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
+import org.jkiss.dbeaver.model.meta.Property;
+import org.jkiss.dbeaver.model.struct.DBSObject;
+
+public class PostgreAvailableExtension implements PostgreObject{
+
+ private final PostgreDatabase database;
+ private final String name;
+ private final long oid;
+ private final String description;
+ private final String version;
+ private final String installed_version;
+ private final boolean installed;
+
+ public PostgreAvailableExtension(PostgreDatabase database,ResultSet dbResult)
+
+ {
+ this.database = database;
+ this.oid = JDBCUtils.safeGetLong(dbResult, "oid");
+ this.name = JDBCUtils.safeGetString(dbResult, "name");
+ this.version = JDBCUtils.safeGetString(dbResult, "default_version");
+ this.installed_version = JDBCUtils.safeGetString(dbResult, "installed_version");
+ installed = installed_version != null;
+ this.description = JDBCUtils.safeGetString(dbResult, "comment");
+ }
+
+ @Override
+ public DBSObject getParentObject() {
+ return null;
+ }
+
+ @Override
+ @Property(viewable = true, order = 1)
+ public String getName() {
+ return name;
+ }
+
+ @Property(viewable = true, order = 2)
+ public String getVersion() {
+ return version;
+ }
+
+ @Property(viewable = true, order = 3)
+ public String getInstalledVersion() {
+ return installed_version;
+ }
+
+ @Override
+ @Property(viewable = true, order = 4)
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public boolean isPersisted() {
+ return false;
+ }
+
+ @Override
+ public long getObjectId() {
+ return oid;
+ }
+
+ @Override
+ public PostgreDataSource getDataSource() {
+ return database.getDataSource();
+ }
+
+ @Override
+ public PostgreDatabase getDatabase() {
+ return database;
+ }
+
+ public boolean isInstalled() {
+ return installed;
+ }
+
+
+
+}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreDatabase.java b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreDatabase.java
index a0b9ff5878f2ea4ce9958310605c3d7a584a0005..57b29afadac8b16041666c936217c72f700c8fb2 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreDatabase.java
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreDatabase.java
@@ -22,6 +22,7 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.postgresql.PostgreConstants;
import org.jkiss.dbeaver.ext.postgresql.PostgreUtils;
+import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema.ExtensionCache;
import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCExecutionPurpose;
@@ -91,6 +92,8 @@ public class PostgreDatabase extends JDBCRemoteInstance
public final ForeignServerCache foreignServerCache = new ForeignServerCache();
public final LanguageCache languageCache = new LanguageCache();
public final EncodingCache encodingCache = new EncodingCache();
+ public final ExtensionCache extensionCache = new ExtensionCache();
+ public final AvailableExtensionCache availableExtensionCache = new AvailableExtensionCache();
public final CollationCache collationCache = new CollationCache();
public final TablespaceCache tablespaceCache = new TablespaceCache();
public final LongKeyMap dataTypeCache = new LongKeyMap<>();
@@ -414,7 +417,20 @@ public class PostgreDatabase extends JDBCRemoteInstance
checkInstanceConnection(monitor);
return encodingCache.getAllObjects(monitor, this);
}
-
+
+ @Association
+ public Collection getExtensions(DBRProgressMonitor monitor)
+ throws DBException {
+ return extensionCache.getAllObjects(monitor, this);
+ }
+
+ @Association
+ public Collection getAvailableExtensions(DBRProgressMonitor monitor)
+ throws DBException {
+ return availableExtensionCache.getAllObjects(monitor, this);
+ }
+
+
@Association
public Collection getCollations(DBRProgressMonitor monitor)
throws DBException {
@@ -1016,6 +1032,65 @@ public class PostgreDatabase extends JDBCRemoteInstance
return new PostgreTablespace(owner, dbResult);
}
}
+
+ class AvailableExtensionCache extends JDBCObjectCache {
+
+ @Override
+ protected JDBCStatement prepareObjectsStatement(@NotNull JDBCSession session, @NotNull PostgreDatabase owner)
+ throws SQLException {
+ final JDBCPreparedStatement dbStat = session.prepareStatement(
+ "SELECT name,default_version,installed_version,comment FROM pg_catalog.pg_available_extensions ORDER BY name"
+ );
+ return dbStat;
+ }
+
+ @Override
+ protected PostgreAvailableExtension fetchObject(@NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult)
+ throws SQLException, DBException {
+ return new PostgreAvailableExtension(owner, dbResult);
+ }
+ }
+
+ class ExtensionCache extends JDBCObjectCache {
+
+ @Override
+ protected JDBCStatement prepareObjectsStatement(@NotNull JDBCSession session, @NotNull PostgreDatabase owner)
+ throws SQLException {
+ final JDBCPreparedStatement dbStat = session.prepareStatement(
+ "SELECT \n" +
+ " e.oid,\n" +
+ " a.rolname oname,\n" +
+ " cfg.tbls,\n" +
+ " e.* \n" +
+ "FROM \n" +
+ " pg_catalog.pg_extension e \n" +
+ " join pg_authid a on a.oid = e.extowner\n" +
+ " join pg_namespace n on n.oid =e.extnamespace\n" +
+ " left join (\n" +
+ " select\n" +
+ " ARRAY_AGG(ns.nspname || '.' || cls.relname) tbls, oid_ext\n" +
+ " from\n" +
+ " (\n" +
+ " select\n" +
+ " unnest(e1.extconfig) oid , e1.oid oid_ext\n" +
+ " from\n" +
+ " pg_catalog.pg_extension e1 ) c \n" +
+ " join pg_class cls on cls.oid = c.oid \n" +
+ " join pg_namespace ns on ns.oid = cls.relnamespace\n" +
+ " group by oid_ext \n" +
+ " ) cfg on cfg.oid_ext = e.oid\n" +
+ "ORDER BY e.oid"
+ );
+ // dbStat.setLong(1, PostgreSchema.this.getObjectId());
+ return dbStat;
+ }
+
+ @Override
+ protected PostgreExtension fetchObject(@NotNull JDBCSession session, @NotNull PostgreDatabase owner, @NotNull JDBCResultSet dbResult)
+ throws SQLException, DBException {
+ return new PostgreExtension(owner, dbResult);
+ }
+ }
public static class SchemaCache extends JDBCObjectLookupCache {
@NotNull
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreExtension.java b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreExtension.java
index 7deaded2101edf91e8d943ad5f2bbbcda801a6bb..b479706851e7be0ee441eb709dffc4bbd775d50d 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreExtension.java
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreExtension.java
@@ -20,15 +20,16 @@ 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.DBUtils;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
+import org.jkiss.dbeaver.model.meta.IPropertyValueListProvider;
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.DBSObject;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.LinkedHashMap;
+import java.util.Collection;
import java.util.Map;
/**
@@ -37,17 +38,29 @@ import java.util.Map;
public class PostgreExtension implements PostgreObject, PostgreScriptObject {
private static final Log log = Log.getLog(PostgreExtension.class);
+
+ private PostgreDatabase database;
- private PostgreSchema schema;
private long oid;
private String name;
+ private String owner;
+ private String tables;
+ private String conditions;
+ private boolean relocatable;
private String version;
private Map tableConditions;
+
+ public PostgreExtension(PostgreDatabase database)
+ {
+ this.database = database;
+ this.owner = "postgres";
+ }
+
- public PostgreExtension(PostgreSchema schema, ResultSet dbResult)
+ public PostgreExtension(PostgreDatabase database, ResultSet dbResult)
throws SQLException
{
- this.schema = schema;
+ this.database = database;
this.loadInfo(dbResult);
}
@@ -57,36 +70,50 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
this.oid = JDBCUtils.safeGetLong(dbResult, "oid");
this.name = JDBCUtils.safeGetString(dbResult, "extname");
this.version = JDBCUtils.safeGetString(dbResult, "extversion");
- try {
- Long[] extTableIDs = JDBCUtils.safeGetArray(dbResult, "extconfig");
- String[] extTableConditions = JDBCUtils.safeGetArray(dbResult, "extcondition");
- if (extTableIDs != null && extTableConditions != null) {
- if (extTableIDs.length != extTableConditions.length) {
- log.error("extconfig.length <> extcondition.length");
- } else {
- tableConditions = new LinkedHashMap<>();
- for (int i = 0; i < extTableIDs.length; i++) {
- tableConditions.put(extTableIDs[i], extTableConditions[i]);
- }
- }
- }
- } catch (Exception e) {
- log.error(e);
- }
+ this.owner = JDBCUtils.safeGetString(dbResult, "oname");
+ this.tables = JDBCUtils.safeGetString(dbResult, "tbls");
+ this.relocatable = JDBCUtils.safeGetBoolean(dbResult, "extrelocatable");
+ this.conditions = JDBCUtils.safeGetString(dbResult, "extcondition");
}
@NotNull
@Override
- @Property(viewable = true, order = 1)
+ @Property(viewable = true,editable = true, order = 1)
public String getName()
{
return name;
}
+
+ public void setName(String name) {
+ this.name = name;
+ }
@NotNull
- @Property(viewable = true, order = 2)
- public PostgreSchema getSchema() {
- return schema;
+ @Property(viewable = true, order = 5)
+ public String getTables() {
+ return tables;
+ }
+
+ @NotNull
+ @Property(viewable = true, order = 6)
+ public String getConditions() {
+ return conditions;
+ }
+
+ @NotNull
+ @Property(viewable = true,editable = true,updatable = true, order = 4, listProvider = SchemaListProvider.class)
+ public String getSchema() {
+ return owner;
+ }
+
+ public void setSchema(String schema) {
+ this.owner = schema;
+ }
+
+ @NotNull
+ @Property(viewable = true, order = 3)
+ public boolean getRelocatable() {
+ return relocatable;
}
@Override
@@ -94,7 +121,7 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
return oid;
}
- @Property(viewable = true, order = 4)
+ @Property(viewable = true, order = 2)
public String getVersion() {
return version;
}
@@ -117,13 +144,13 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
@Override
public DBSObject getParentObject()
{
- return schema;
+ return database;
}
@NotNull
@Override
public PostgreDataSource getDataSource() {
- return schema.getDataSource();
+ return database.getDataSource();
}
@Override
@@ -134,7 +161,7 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
@NotNull
@Override
public PostgreDatabase getDatabase() {
- return schema.getDatabase();
+ return database;
}
@Override
@@ -143,7 +170,7 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
"-- Extension: " + getName() + "\n\n" +
"-- DROP EXTENSION " + getName() + ";\n\n" +
"CREATE EXTENSION " + getName() + "\n\t" +
- "SCHEMA " + DBUtils.getQuotedIdentifier(getSchema()) + "\n\t" +
+ "SCHEMA \"" + getSchema() + "\"\n\t" +
"VERSION " + version;
}
@@ -151,4 +178,23 @@ public class PostgreExtension implements PostgreObject, PostgreScriptObject {
public void setObjectDefinitionText(String sourceText) throws DBException {
}
+
+ public static class SchemaListProvider implements IPropertyValueListProvider {
+ @Override
+ public boolean allowCustomValue()
+ {
+ return false;
+ }
+ @Override
+ public Object[] getPossibleValues(PostgreExtension object)
+ {
+ try {
+ Collection schemas = object.getDatabase().getSchemas(new VoidProgressMonitor());
+ return schemas.toArray(new Object[schemas.size()]);
+ } catch (DBException e) {
+ log.error(e);
+ return new Object[0];
+ }
+ }
+ }
}
diff --git a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreSchema.java b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreSchema.java
index 86561a200218140a23e3651b611d242bec768ba6..459125ea5d9edcb1e1b2b362bb3c5156f3df1318 100644
--- a/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreSchema.java
+++ b/plugins/org.jkiss.dbeaver.ext.postgresql/src/org/jkiss/dbeaver/ext/postgresql/model/PostgreSchema.java
@@ -439,9 +439,30 @@ public class PostgreSchema implements DBSSchema, DBPNamedObject2, DBPSaveableObj
protected JDBCStatement prepareObjectsStatement(@NotNull JDBCSession session, @NotNull PostgreSchema owner)
throws SQLException {
final JDBCPreparedStatement dbStat = session.prepareStatement(
- "SELECT e.oid,e.* FROM pg_catalog.pg_extension e " +
- "\nWHERE e.extnamespace=?" +
- "\nORDER BY e.oid"
+ "SELECT \n" +
+ " e.oid,\n" +
+ " a.rolname oname,\n" +
+ " cfg.tbls,\n" +
+ " e.* \n" +
+ "FROM \n" +
+ " pg_catalog.pg_extension e \n" +
+ " join pg_authid a on a.oid = e.extowner\n" +
+ " join pg_namespace n on n.oid =e.extnamespace\n" +
+ " left join (\n" +
+ " select\n" +
+ " ARRAY_AGG(ns.nspname || '.' || cls.relname) tbls, oid_ext\n" +
+ " from\n" +
+ " (\n" +
+ " select\n" +
+ " unnest(e1.extconfig) oid , e1.oid oid_ext\n" +
+ " from\n" +
+ " pg_catalog.pg_extension e1 ) c \n" +
+ " join pg_class cls on cls.oid = c.oid \n" +
+ " join pg_namespace ns on ns.oid = cls.relnamespace\n" +
+ " group by oid_ext \n" +
+ " ) cfg on cfg.oid_ext = e.oid\n" +
+ "\nWHERE e.extnamespace=?\n" +
+ "ORDER BY e.oid"
);
dbStat.setLong(1, PostgreSchema.this.getObjectId());
return dbStat;
@@ -450,7 +471,8 @@ public class PostgreSchema implements DBSSchema, DBPNamedObject2, DBPSaveableObj
@Override
protected PostgreExtension fetchObject(@NotNull JDBCSession session, @NotNull PostgreSchema owner, @NotNull JDBCResultSet dbResult)
throws SQLException, DBException {
- return new PostgreExtension(owner, dbResult);
+ //return new PostgreExtension(owner, dbResult);
+ return null;
}
}