From 63ecafc5739c8764b3c619f3dcb4fbe52bf2208c Mon Sep 17 00:00:00 2001 From: Claus Nagel Date: Sun, 28 Jan 2024 10:39:29 +0100 Subject: [PATCH] fixed global-to-local appearance converter to avoid duplicate exports --- .../content/DBGlobalToLocalAppearance.java | 101 ++++-------------- 1 file changed, 19 insertions(+), 82 deletions(-) diff --git a/impexp-core/src/main/java/org/citydb/core/operation/exporter/database/content/DBGlobalToLocalAppearance.java b/impexp-core/src/main/java/org/citydb/core/operation/exporter/database/content/DBGlobalToLocalAppearance.java index 855049ac7..1fbcc38b0 100644 --- a/impexp-core/src/main/java/org/citydb/core/operation/exporter/database/content/DBGlobalToLocalAppearance.java +++ b/impexp-core/src/main/java/org/citydb/core/operation/exporter/database/content/DBGlobalToLocalAppearance.java @@ -30,7 +30,7 @@ import org.citydb.config.Config; import org.citydb.config.project.exporter.OutputFormat; -import org.citydb.core.database.schema.mapping.MappingConstants; +import org.citydb.core.database.schema.TableEnum; import org.citydb.core.operation.exporter.CityGMLExportException; import org.citydb.core.operation.exporter.util.AppearanceRemover; import org.citydb.core.query.Query; @@ -38,14 +38,10 @@ import org.citydb.core.query.builder.sql.AppearanceFilterBuilder; import org.citydb.core.util.CoreConstants; import org.citydb.sqlbuilder.expression.LiteralList; -import org.citydb.sqlbuilder.expression.LiteralSelectExpression; -import org.citydb.sqlbuilder.expression.PlaceHolder; import org.citydb.sqlbuilder.schema.Table; import org.citydb.sqlbuilder.select.PredicateToken; import org.citydb.sqlbuilder.select.Select; -import org.citydb.sqlbuilder.select.join.JoinFactory; import org.citydb.sqlbuilder.select.operator.comparison.ComparisonFactory; -import org.citydb.sqlbuilder.select.operator.comparison.ComparisonName; import org.citygml4j.builder.copy.CopyBuilder; import org.citygml4j.builder.copy.DeepCopyBuilder; import org.citygml4j.model.citygml.appearance.Appearance; @@ -64,16 +60,10 @@ public class DBGlobalToLocalAppearance extends AbstractAppearanceExporter { private final Connection connection; - private final PreparedStatement psBulk; - private final PreparedStatement psSelect; - private final Select appearanceQuery; - private final Table textureParam; - private final boolean replaceIds; private final boolean handleImplicitGeometries; private final AppearanceRemover appearanceRemover; - private final Map batches; - private final int batchSize; + private final Table textureParam; private CopyBuilder copyBuilder; private ChildInfo childInfo; @@ -95,43 +85,29 @@ public DBGlobalToLocalAppearance(Connection connection, Query query, CityGMLExpo } appearanceRemover = new AppearanceRemover(); - batches = new LinkedHashMap<>(); - batchSize = exporter.getFeatureBatchSize(); - String schema = exporter.getDatabaseAdapter().getConnectionDetails().getSchema(); - - Table appearance = new Table("appearance", schema); - Table appearToSurfaceData = new Table("appear_to_surface_data", schema); - Table surfaceData = new Table("surface_data", schema); - textureParam = new Table("textureparam", schema); - - appearanceQuery = new Select().setDistinct(true) - .addProjection(appearance.getColumn(MappingConstants.ID)) - .addJoin(JoinFactory.inner(appearToSurfaceData, "appearance_id", ComparisonName.EQUAL_TO, appearance.getColumn(MappingConstants.ID))) - .addJoin(JoinFactory.inner(surfaceData, MappingConstants.ID, ComparisonName.EQUAL_TO, appearToSurfaceData.getColumn("surface_data_id"))) - .addJoin(JoinFactory.inner(textureParam, "surface_data_id", ComparisonName.EQUAL_TO, surfaceData.getColumn(MappingConstants.ID))) - .addSelection(ComparisonFactory.isNull(appearance.getColumn("cityobject_id"))); + select = new Select(select).setDistinct(true) + .addSelection(ComparisonFactory.isNull(table.getColumn("cityobject_id"))); + + textureParam = select.getInvolvedTables().stream() + .filter(table -> TableEnum.TEXTUREPARAM.getName().equals(table.getName())) + .findFirst().orElse(null); + if (textureParam == null) { + throw new CityGMLExportException("Failed to build global-to-local appearance query."); + } // add appearance theme filter if (query.isSetAppearanceFilter()) { try { PredicateToken predicate = new AppearanceFilterBuilder(exporter.getDatabaseAdapter()) - .buildAppearanceFilter(query.getAppearanceFilter(), appearance.getColumn("theme")); - appearanceQuery.addSelection(predicate); + .buildAppearanceFilter(query.getAppearanceFilter(), table.getColumn("theme")); + select.addSelection(predicate); } catch (QueryBuildException e) { throw new CityGMLExportException("Failed to build appearance filter.", e); } } - - String placeHolders = String.join(",", Collections.nCopies(batchSize, "?")); - psBulk = connection.prepareStatement(new Select(select) - .addSelection(ComparisonFactory.in(table.getColumn("id"), new LiteralSelectExpression(placeHolders))).toString()); - - psSelect = connection.prepareStatement(new Select(select) - .addSelection(ComparisonFactory.equalTo(table.getColumn("id"), new PlaceHolder<>())).toString()); } protected Collection doExport(AbstractCityObject cityObject) throws CityGMLExportException, SQLException { - List unconverted = new ArrayList<>(); Set surfaceGeometryIds = new HashSet<>(); Map> targets = new EnumMap<>(GeometryType.class); @@ -157,60 +133,23 @@ public void visit(AbstractGeometry geometry) { }); if (!surfaceGeometryIds.isEmpty()) { - Select select = new Select(appearanceQuery) + Select select = new Select(this.select) .addSelection(ComparisonFactory.in(textureParam.getColumn("surface_geometry_id"), new LiteralList(surfaceGeometryIds.toArray(new Long[0])))); + try (PreparedStatement stmt = exporter.getDatabaseAdapter().getSQLAdapter().prepareStatement(select, connection); ResultSet rs = stmt.executeQuery()) { - while (rs.next()) { - batches.put(rs.getLong(1), cityObject); - if (batches.size() == batchSize) { - unconverted.addAll(executeBatch(targets)); - } - } - - if (!batches.isEmpty()) { - unconverted.addAll(executeBatch(targets)); - } - } - } - - return unconverted; - } - - private List executeBatch(Map> targets) throws CityGMLExportException, SQLException { - if (!batches.isEmpty()) { - try { - Map appearances; - if (batches.size() == 1) { - psSelect.setLong(1, batches.entrySet().iterator().next().getKey()); - try (ResultSet rs = psSelect.executeQuery()) { - appearances = doExport(rs); - } - } else { - int i = 1; - Long[] ids = batches.keySet().toArray(new Long[0]); - for (int j = 0; j < batchSize; j++) { - psBulk.setLong(i + j, j < ids.length ? ids[j] : 0); - } - - try (ResultSet rs = psBulk.executeQuery()) { - appearances = doExport(rs); - } - } - + Map appearances = doExport(rs); if (!appearances.isEmpty()) { - return postprocess(appearances, targets); + return postprocess(appearances, targets, cityObject); } - } finally { - batches.clear(); } } return Collections.emptyList(); } - private List postprocess(Map appearances, Map> targets) { + private List postprocess(Map appearances, Map> targets, AbstractCityObject cityObject) { List globalAppearances = new ArrayList<>(); Set implicitGeometryTargets = targets.get(GeometryType.IMPLICIT_GEOMETRY); if (implicitGeometryTargets != null) { @@ -228,7 +167,6 @@ private List postprocess(Map appearances, Map postprocess(Map appearances, Map