提交 a7bc5fd4 编写于 作者: L LonwoLonwo

#12374 append option modifiers for views, materialized views and distributed...

#12374 append option modifiers for views, materialized views and distributed info for Greenplum materialized views
上级 d71cde53
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 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 org.jkiss.dbeaver.ext.greenplum.model;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreMaterializedView;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableColumn;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.utils.CommonUtils;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class GreenplumMaterializedView extends PostgreMaterializedView {
private static final Log log = Log.getLog(GreenplumMaterializedView.class);
private int[] distributionColumns;
private boolean supportsReplicatedDistribution;
public GreenplumMaterializedView(PostgreSchema catalog, ResultSet dbResult) {
super(catalog, dbResult);
if (catalog.getDataSource().isServerVersionAtLeast(9, 1)) {
supportsReplicatedDistribution = true;
}
}
public GreenplumMaterializedView(PostgreSchema catalog) {
super(catalog);
}
private List<PostgreTableColumn> getDistributionPolicy(DBRProgressMonitor monitor) throws DBException {
if (distributionColumns == null) {
try {
distributionColumns = GreenplumUtils.readDistributedColumns(monitor, this);
} catch (Throwable e) {
log.error("Error reading distribution policy", e);
}
if (distributionColumns == null) {
distributionColumns = new int[0];
}
}
if (distributionColumns.length == 0) {
return null;
}
List<PostgreTableColumn> columns = new ArrayList<>(distributionColumns.length);
for (int i = 0; i < distributionColumns.length; i++) {
PostgreTableColumn attr = getAttributeByPos(monitor, distributionColumns[i]);
if (attr == null) {
log.debug("Bad policy attribute position: " + distributionColumns[i]);
} else {
columns.add(attr);
}
}
return columns;
}
@Override
public void appendTableModifiers(DBRProgressMonitor monitor, StringBuilder ddl) {
try {
List<PostgreTableColumn> distributionColumns = getDistributionPolicy(monitor);
if (CommonUtils.isEmpty(distributionColumns)) {
distributionColumns = GreenplumUtils.getDistributionTableColumns(monitor, distributionColumns, this);
}
GreenplumUtils.addObjectModifiersToDDL(monitor, ddl, this, distributionColumns, supportsReplicatedDistribution);
} catch (DBException e) {
log.error("Error reading Greenplum table properties", e);
}
}
}
......@@ -20,27 +20,15 @@
*/
package org.jkiss.dbeaver.ext.greenplum.model;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.postgresql.PostgreUtils;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableColumn;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableConstraint;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableRegular;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSEntityAttribute;
import org.jkiss.dbeaver.model.struct.DBSEntityConstraintType;
import org.jkiss.utils.CommonUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
......@@ -70,7 +58,7 @@ public class GreenplumTable extends PostgreTableRegular {
private List<PostgreTableColumn> getDistributionPolicy(DBRProgressMonitor monitor) throws DBException {
if (distributionColumns == null) {
try {
distributionColumns = readDistributedColumns(monitor);
distributionColumns = GreenplumUtils.readDistributedColumns(monitor, this);
} catch (Throwable e) {
log.error("Error reading distribution policy", e);
}
......@@ -94,120 +82,18 @@ public class GreenplumTable extends PostgreTableRegular {
return columns;
}
private List<PostgreTableColumn> getDistributionTableColumns(DBRProgressMonitor monitor, List<PostgreTableColumn> distributionColumns) throws DBException {
// Get primary key
PostgreTableConstraint pk = null;
for (PostgreTableConstraint tc : CommonUtils.safeCollection(getConstraints(monitor))) {
if (tc.getConstraintType() == DBSEntityConstraintType.PRIMARY_KEY) {
pk = tc;
break;
}
}
if (pk != null) {
List<DBSEntityAttribute> pkAttrs = DBUtils.getEntityAttributes(monitor, pk);
if (!CommonUtils.isEmpty(pkAttrs)) {
distributionColumns = new ArrayList<>(pkAttrs.size());
for (DBSEntityAttribute attr : pkAttrs) {
distributionColumns.add((PostgreTableColumn) attr);
}
}
}
return distributionColumns;
}
@Nullable
private int[] readDistributedColumns(DBRProgressMonitor monitor) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, this, "Read Greenplum table distributed columns")) {
try (JDBCStatement dbStat = session.createStatement()) {
if (((GreenplumDataSource) getDataSource()).isGreenplumVersionAtLeast(session.getProgressMonitor(), 6, 0)) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT distkey FROM pg_catalog.gp_distribution_policy WHERE localoid=" + getObjectId())) {
if (dbResult.next()) {
return PostgreUtils.getIntVector(JDBCUtils.safeGetObject(dbResult, 1));
} else {
return null;
}
}
} else {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT attrnums FROM pg_catalog.gp_distribution_policy WHERE localoid=" + getObjectId())) {
if (dbResult.next()) {
return PostgreUtils.getIntVector(JDBCUtils.safeGetObject(dbResult, 1));
} else {
return null;
}
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
private boolean isDistributedByReplicated(DBRProgressMonitor monitor) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, this, "Read Greenplum table distributed columns")) {
try (JDBCStatement dbStat = session.createStatement()) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT policytype FROM pg_catalog.gp_distribution_policy WHERE localoid=" + getObjectId())) {
if (dbResult.next()) {
return CommonUtils.equalObjects(JDBCUtils.safeGetString(dbResult, 1), "r");
} else {
return false;
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
@Override
public void appendTableModifiers(DBRProgressMonitor monitor, StringBuilder ddl) {
try {
List<PostgreTableColumn> distributionColumns = getDistributionPolicy(monitor);
if (CommonUtils.isEmpty(distributionColumns)) {
distributionColumns = getDistributionTableColumns(monitor, distributionColumns);
}
ddl.append("\nDISTRIBUTED ");
if (supportsReplicatedDistribution && isPersisted() && isDistributedByReplicated(monitor)) {
ddl.append("REPLICATED");
} else if (!CommonUtils.isEmpty(distributionColumns)) {
ddl.append("BY (");
for (int i = 0; i < distributionColumns.size(); i++) {
if (i > 0) ddl.append(", ");
ddl.append(DBUtils.getQuotedIdentifier(distributionColumns.get(i)));
}
ddl.append(")");
} else {
ddl.append("RANDOMLY");
distributionColumns = GreenplumUtils.getDistributionTableColumns(monitor, distributionColumns, this);
}
String partitionData = isPersisted() ? getPartitionData(monitor) : null;
if (partitionData != null) {
ddl.append("\n");
ddl.append(partitionData);
}
GreenplumUtils.addObjectModifiersToDDL(monitor, ddl, this, distributionColumns, supportsReplicatedDistribution);
} catch (DBException e) {
log.error("Error reading Greenplum table properties", e);
}
}
private String getPartitionData(DBRProgressMonitor monitor) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, this, "Read Greenplum table partition data")) {
try (JDBCStatement dbStat = session.createStatement()) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT pg_get_partition_def('" + getSchema().getName() + "." + getName() + "'::regclass, true, false);")) {
if (dbResult.next()) {
String result = dbResult.getString(1);
if (result != null && result.startsWith("PARTITION ")) {
return result;
}
return null;
} else {
return null;
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2021 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 org.jkiss.dbeaver.ext.greenplum.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.ext.postgresql.PostgreUtils;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableColumn;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableConstraint;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableReal;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement;
import org.jkiss.dbeaver.model.impl.jdbc.JDBCUtils;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSEntityAttribute;
import org.jkiss.dbeaver.model.struct.DBSEntityConstraintType;
import org.jkiss.utils.CommonUtils;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class GreenplumUtils {
@Nullable
static int[] readDistributedColumns(@NotNull DBRProgressMonitor monitor, @NotNull PostgreTableReal table) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, table, "Read Greenplum table distributed columns")) {
try (JDBCStatement dbStat = session.createStatement()) {
if (((GreenplumDataSource) table.getDataSource()).isGreenplumVersionAtLeast(session.getProgressMonitor(), 6, 0)) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT distkey FROM pg_catalog.gp_distribution_policy WHERE localoid=" + table.getObjectId())) {
if (dbResult.next()) {
return PostgreUtils.getIntVector(JDBCUtils.safeGetObject(dbResult, 1));
} else {
return null;
}
}
} else {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT attrnums FROM pg_catalog.gp_distribution_policy WHERE localoid=" + table.getObjectId())) {
if (dbResult.next()) {
return PostgreUtils.getIntVector(JDBCUtils.safeGetObject(dbResult, 1));
} else {
return null;
}
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
static List<PostgreTableColumn> getDistributionTableColumns(@NotNull DBRProgressMonitor monitor, List<PostgreTableColumn> distributionColumns, @NotNull PostgreTableReal table) throws DBException {
// Get primary key
PostgreTableConstraint pk = null;
for (PostgreTableConstraint tc : CommonUtils.safeCollection(table.getConstraints(monitor))) {
if (tc.getConstraintType() == DBSEntityConstraintType.PRIMARY_KEY) {
pk = tc;
break;
}
}
if (pk != null) {
List<DBSEntityAttribute> pkAttrs = DBUtils.getEntityAttributes(monitor, pk);
if (!CommonUtils.isEmpty(pkAttrs)) {
distributionColumns = new ArrayList<>(pkAttrs.size());
for (DBSEntityAttribute attr : pkAttrs) {
distributionColumns.add((PostgreTableColumn) attr);
}
}
}
return distributionColumns;
}
private static boolean isDistributedByReplicated(DBRProgressMonitor monitor, @NotNull PostgreTableReal table) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, table, "Read Greenplum table distributed columns")) {
try (JDBCStatement dbStat = session.createStatement()) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT policytype FROM pg_catalog.gp_distribution_policy WHERE localoid=" + table.getObjectId())) {
if (dbResult.next()) {
return CommonUtils.equalObjects(JDBCUtils.safeGetString(dbResult, 1), "r");
} else {
return false;
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
private static String getPartitionData(@NotNull DBRProgressMonitor monitor, @NotNull PostgreTableReal table) throws DBCException {
try (JDBCSession session = DBUtils.openMetaSession(monitor, table, "Read Greenplum table partition data")) {
try (JDBCStatement dbStat = session.createStatement()) {
try (JDBCResultSet dbResult = dbStat.executeQuery("SELECT pg_get_partition_def('" + table.getSchema().getName() + "." + table.getName() + "'::regclass, true, false);")) {
if (dbResult.next()) {
String result = dbResult.getString(1);
if (result != null && result.startsWith("PARTITION ")) {
return result;
}
return null;
} else {
return null;
}
}
} catch (SQLException e) {
throw new DBCException(e, session.getExecutionContext());
}
}
}
static void addObjectModifiersToDDL(@NotNull DBRProgressMonitor monitor, @NotNull StringBuilder ddl, @NotNull PostgreTableReal table, List<PostgreTableColumn> distributionColumns, boolean supportsReplicatedDistribution) throws DBCException {
ddl.append("\nDISTRIBUTED ");
if (supportsReplicatedDistribution && table.isPersisted() && GreenplumUtils.isDistributedByReplicated(monitor, table)) {
ddl.append("REPLICATED");
} else if (!CommonUtils.isEmpty(distributionColumns)) {
ddl.append("BY (");
for (int i = 0; i < distributionColumns.size(); i++) {
if (i > 0) ddl.append(", ");
ddl.append(DBUtils.getQuotedIdentifier(distributionColumns.get(i)));
}
ddl.append(")");
} else {
ddl.append("RANDOMLY");
}
String partitionData = table.isPersisted() ? GreenplumUtils.getPartitionData(monitor, table) : null;
if (partitionData != null) {
ddl.append("\n");
ddl.append(partitionData);
}
}
}
......@@ -63,6 +63,8 @@ public class PostgreServerGreenplum extends PostgreServerExtensionBase {
return new GreenplumExternalTable(schema, dbResult);
}
return new GreenplumTable(schema, dbResult);
} else if (kind == PostgreClass.RelKind.m) {
return new GreenplumMaterializedView(schema, dbResult);
}
return super.createRelationOfClass(schema, kind, dbResult);
}
......@@ -71,6 +73,8 @@ public class PostgreServerGreenplum extends PostgreServerExtensionBase {
public PostgreTableBase createNewRelation(DBRProgressMonitor monitor, PostgreSchema schema, PostgreClass.RelKind kind, Object copyFrom) throws DBException {
if (kind == PostgreClass.RelKind.r) {
return new GreenplumTable(schema);
} else if (kind == PostgreClass.RelKind.m) {
return new GreenplumMaterializedView(schema);
}
return super.createNewRelation(monitor, schema, kind, copyFrom);
}
......
......@@ -538,6 +538,7 @@ public class PostgreUtils {
if (entityEditor != null) {
entityEditor.appendViewDeclarationPostfix(monitor, sql, view);
}
view.appendTableModifiers(monitor, sql);
sql.append(";");
return sql.toString();
}
......
......@@ -30,6 +30,7 @@ import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.impl.edit.SQLDatabasePersistAction;
import org.jkiss.dbeaver.model.impl.sql.edit.struct.SQLTableManager;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.utils.ArrayUtils;
import java.util.List;
import java.util.Map;
......@@ -62,7 +63,11 @@ public class PostgreMViewManager extends PostgreViewManager {
@Override
public void appendViewDeclarationPrefix(DBRProgressMonitor monitor, StringBuilder sqlBuf, PostgreViewBase view) throws DBException {
PostgreMaterializedView mview = (PostgreMaterializedView)view;
PostgreMaterializedView mview = (PostgreMaterializedView) view;
String[] relOptions = mview.getRelOptions();
if (!ArrayUtils.isEmpty(relOptions)) {
sqlBuf.append("\nWITH(").append(String.join("," , relOptions)).append(")");
}
PostgreTablespace tablespace = mview.getTablespace(monitor);
if (tablespace != null) {
sqlBuf.append("\nTABLESPACE ").append(DBUtils.getQuotedIdentifier(tablespace));
......
......@@ -32,6 +32,7 @@ import org.jkiss.dbeaver.model.impl.sql.edit.struct.SQLTableManager;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.struct.cache.DBSObjectCache;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import java.util.List;
......@@ -133,7 +134,10 @@ public class PostgreViewManager extends PostgreTableManagerBase implements DBEOb
}
public void appendViewDeclarationPrefix(DBRProgressMonitor monitor, StringBuilder sqlBuf, PostgreViewBase view) throws DBException {
String[] relOptions = view.getRelOptions();
if (!ArrayUtils.isEmpty(relOptions)) {
sqlBuf.append("\nWITH(").append(String.join("," , relOptions)).append(")");
}
}
public void appendViewDeclarationPostfix(DBRProgressMonitor monitor, StringBuilder sqlBuf, PostgreViewBase view) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册