Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added calculation of the bounding box across multiple geometry columns for PostgreSQL (3.5) #1729

Open
wants to merge 2 commits into
base: 3.5-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
----------------------------------------------------------------------------*/
package org.deegree.sqldialect;

import org.deegree.commons.jdbc.TableName;
import org.slf4j.Logger;

import java.util.List;

import static org.slf4j.LoggerFactory.getLogger;

/**
* Implementations provide the vendor-specific behavior for a spatial DBMS so it can be
* accessed by deegree.
Expand All @@ -43,6 +50,8 @@
*/
public abstract class AbstractSQLDialect implements SQLDialect {

private static final Logger LOG = getLogger(AbstractSQLDialect.class);

private char defaultEscapeChar = Character.UNASSIGNED;

@Override
Expand All @@ -60,4 +69,15 @@ public boolean isRowLimitingCapable() {
return true;
}

@Override
public String getSelectBBox(List<String> columns, List<TableName> tables) {
if (columns.size() > 1 || tables.size() > 1)
LOG.warn("Multiple geometry columns are currently not supported. Using first.");
StringBuilder sql = new StringBuilder("SELECT ");
sql.append(getBBoxAggregateSnippet(columns.get(0)));
sql.append(" FROM ");
sql.append(tables.get(0));
return sql.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,22 @@ AbstractWhereBuilder getWhereBuilder(PropertyNameMapper mapper, OperatorFilter f
/**
* Returns an SQL snippet for SELECTing the aggregate bounding box of the given
* column.
* @param colummn name of the column that stores the bounding box, never
* @param column name of the column that stores the bounding box, never
* <code>null</code>
* @return SQL snippet, never <code>null</code>
*/
String getBBoxAggregateSnippet(String colummn);
String getBBoxAggregateSnippet(String column);

/**
* Returns an SQL snippet for SELECTing the aggregate bounding box of the given
* columns.
* @param columns list of column names that stores the bounding box, never
* <code>null</code>
* @param tables list of table names that stores the bounding box, never
* <code>null</code>
* @return SQL snippet, never <code>null</code>
*/
String getSelectBBox(List<String> columns, List<TableName> tables);

/**
* Converts the value that has been SELECTed via
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public String getUndefinedSrid() {
}

@Override
public String getBBoxAggregateSnippet(String colummn) {
public String getBBoxAggregateSnippet(String column) {
return "1";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Collectors;

import org.deegree.commons.jdbc.SQLIdentifier;
import org.deegree.commons.jdbc.TableName;
Expand Down Expand Up @@ -195,6 +196,29 @@ public String getBBoxAggregateSnippet(String column) {
return sql.toString();
}

@Override
public String getSelectBBox(List<String> columns, List<TableName> tables) {
if (columns.size() <= 1) {
return super.getSelectBBox(columns, tables);
}
StringBuilder sql = new StringBuilder("SELECT ");
sql.append("ST_Extent( u.allbboxes )::BOX2D FROM (");
// subquery start
sql.append("SELECT ST_Collect( ARRAY[ ");
boolean isFirst = true;
for (String column : columns) {
if (!isFirst)
sql.append(", ");
sql.append(getBBoxAggregateSnippet(column));
isFirst = false;
}
sql.append(" ] ) as allbboxes FROM ");
sql.append(tables.stream().map(SQLIdentifier::toString).collect(Collectors.joining(", ")));
// subquery end
sql.append(") u");
return sql.toString();
}

@Override
public Envelope getBBoxAggregateValue(ResultSet rs, int colIdx, ICRS crs) throws SQLException {
Envelope env = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,40 +157,53 @@ public List<SortCriterion> getDefaultSortCriteria() {
* defined)
*/
public Pair<TableName, GeometryMapping> getDefaultGeometryMapping() {
List<Pair<TableName, GeometryMapping>> defaultGeometryMappings = getAllGeometryMappings();
if (defaultGeometryMappings.isEmpty())
return null;
return defaultGeometryMappings.get(0);
}

/**
* Returns all {@link GeometryMapping}.
* @return all geometry mappings, may be <code>empty</code> (no geometry mapping
* defined) but never <code>null</code>
*/
public List<Pair<TableName, GeometryMapping>> getAllGeometryMappings() {
List<Pair<TableName, GeometryMapping>> defaultGeometryMappings = new ArrayList<>();
addGeometryMappings(defaultGeometryMappings);
return defaultGeometryMappings;
}

private void addGeometryMappings(List<Pair<TableName, GeometryMapping>> defaultGeometryMappings) {
TableName table = getFtTable();
for (Mapping particle : particles) {
if (particle instanceof GeometryMapping) {
List<TableJoin> joins = particle.getJoinedTable();
if (joins != null && !joins.isEmpty()) {
table = joins.get(joins.size() - 1).getToTable();
}
return new Pair<TableName, GeometryMapping>(table, (GeometryMapping) particle);
defaultGeometryMappings.add(new Pair<>(table, (GeometryMapping) particle));
}
}
for (Mapping particle : particles) {
TableName propTable = table;
if (particle instanceof CompoundMapping) {
TableName propTable = table;
List<TableJoin> joins = particle.getJoinedTable();
if (joins != null && !joins.isEmpty()) {
propTable = joins.get(joins.size() - 1).getToTable();
}
Pair<TableName, GeometryMapping> gm = getDefaultGeometryMapping(propTable, (CompoundMapping) particle);
if (gm != null) {
return gm;
}
addGeometryMappings(defaultGeometryMappings, propTable, (CompoundMapping) particle);
}
}
return null;
}

private Pair<TableName, GeometryMapping> getDefaultGeometryMapping(TableName table, CompoundMapping complex) {
private void addGeometryMappings(List<Pair<TableName, GeometryMapping>> defaultGeometryMappings, TableName table,
CompoundMapping complex) {
for (Mapping particle : complex.getParticles()) {
if (particle instanceof GeometryMapping) {
List<TableJoin> joins = particle.getJoinedTable();
if (joins != null && !joins.isEmpty()) {
table = joins.get(joins.size() - 1).getToTable();
}
return new Pair<TableName, GeometryMapping>(table, (GeometryMapping) particle);
defaultGeometryMappings.add(new Pair<>(table, (GeometryMapping) particle));
}
}
for (Mapping particle : complex.getParticles()) {
Expand All @@ -200,13 +213,9 @@ private Pair<TableName, GeometryMapping> getDefaultGeometryMapping(TableName tab
if (joins != null && !joins.isEmpty()) {
propTable = joins.get(joins.size() - 1).getToTable();
}
Pair<TableName, GeometryMapping> gm = getDefaultGeometryMapping(propTable, (CompoundMapping) particle);
if (gm != null) {
return gm;
}
addGeometryMappings(defaultGeometryMappings, propTable, (CompoundMapping) particle);
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.xml.namespace.QName;

Expand Down Expand Up @@ -488,25 +489,36 @@ private Envelope calcEnvelope(FeatureTypeMapping ftMapping, Connection conn) thr

LOG.trace("Determining BBOX for feature type '{}' (relational mode)", ftMapping.getFeatureType());

String column = null;
Pair<TableName, GeometryMapping> propMapping = ftMapping.getDefaultGeometryMapping();
if (propMapping == null) {
List<Pair<TableName, GeometryMapping>> geometryMappings = ftMapping.getAllGeometryMappings();
if (geometryMappings.isEmpty()) {
return null;
}
MappingExpression me = propMapping.second.getMapping();
if (me == null || !(me instanceof DBField)) {
String msg = "Cannot determine BBOX for feature type '" + ftMapping.getFeatureType()
+ "' (relational mode).";
LOG.warn(msg);

boolean containsUnsupportedMapping = geometryMappings.stream().anyMatch(geometryMapping -> {
MappingExpression mapping = geometryMapping.second.getMapping();
return mapping == null || !(mapping instanceof DBField);
});
if (containsUnsupportedMapping) {
LOG.warn("Cannot determine BBOX for feature type '{}' (relational mode).", ftMapping.getFeatureType());
return null;
}
long noOfDifferentCrs = geometryMappings.stream()
.map(geometryMapping -> geometryMapping.second.getCRS())
.distinct()
.count();
if (noOfDifferentCrs > 1) {
LOG.warn("Multiple geometries with different CRS are currently not supported");
return null;
}
column = ((DBField) me).getColumn();

Envelope env = null;
StringBuilder sql = new StringBuilder("SELECT ");
sql.append(dialect.getBBoxAggregateSnippet(column));
sql.append(" FROM ");
sql.append(propMapping.first);
List<String> columns = geometryMappings.stream()
.map(geometryMapping -> ((DBField) geometryMapping.second.getMapping()).getColumn())
.collect(Collectors.toList());
List<TableName> uniqueTableNames = geometryMappings.stream()
.map(geometryMapping -> geometryMapping.first)
.distinct()
.collect(Collectors.toUnmodifiableList());
String sql = dialect.getSelectBBox(columns, uniqueTableNames);

Statement stmt = null;
ResultSet rs = null;
Expand All @@ -515,8 +527,8 @@ private Envelope calcEnvelope(FeatureTypeMapping ftMapping, Connection conn) thr
LOG.debug("Executing envelope SELECT: " + sql);
rs = stmt.executeQuery(sql.toString());
rs.next();
ICRS crs = propMapping.second.getCRS();
env = dialect.getBBoxAggregateValue(rs, 1, crs);
ICRS crs = geometryMappings.get(0).second.getCRS();
return dialect.getBBoxAggregateValue(rs, 1, crs);
}
catch (SQLException e) {
LOG.debug(e.getMessage(), e);
Expand All @@ -525,7 +537,6 @@ private Envelope calcEnvelope(FeatureTypeMapping ftMapping, Connection conn) thr
finally {
release(rs, stmt, null);
}
return env;
}

private Envelope calcEnvelope(QName ftName, BlobMapping blobMapping, Connection conn) throws FeatureStoreException {
Expand Down