Skip to content

Commit

Permalink
Merge pull request #30 from 3dcitydb/feature-limit-and-sorting
Browse files Browse the repository at this point in the history
Add limit option and sorting to Query API
  • Loading branch information
clausnagel authored Jul 4, 2024
2 parents 27e60de + 846a38d commit 63ff50a
Show file tree
Hide file tree
Showing 30 changed files with 874 additions and 20 deletions.
1 change: 1 addition & 0 deletions citydb-cli/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
exports org.citydb.cli.exporter.citygml;
exports org.citydb.cli.exporter.cityjson;
exports org.citydb.cli.exporter.options;
exports org.citydb.cli.exporter.util;
exports org.citydb.cli.extension;
exports org.citydb.cli.importer;
exports org.citydb.cli.importer.citygml;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* citydb-tool - Command-line tool for the 3D City Database
* https://www.3dcitydb.org/
*
* Copyright 2022-2024
* virtualcitysystems GmbH, Germany
* https://vc.systems/
*
* 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.citydb.cli.common;

import org.citydb.query.limit.CountLimit;
import picocli.CommandLine;

public class CountLimitOptions implements Option {
@CommandLine.Option(names = "--limit", paramLabel = "<count>",
description = "Maximum number of features to process.")
private Long limit;

@CommandLine.Option(names = "--start-index", paramLabel = "<index>",
description = "Index within the result set from which features are processed.")
private Long startIndex;

public CountLimit getCountLimit() {
return limit != null || startIndex != null ?
new CountLimit()
.setLimit(limit)
.setStartIndex(startIndex) :
null;
}

@Override
public void preprocess(CommandLine commandLine) throws Exception {
if (limit != null && limit < 0) {
throw new CommandLine.ParameterException(commandLine,
"Error: Count limit must be a non-negative integer but was '" + limit + "'");
} else if (startIndex != null && startIndex < 0) {
throw new CommandLine.ParameterException(commandLine,
"Error: Start index must be a non-negative integer but was '" + startIndex + "'");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class FilterOptions {
description = "SRID or identifier of the CRS to use for geometries in the filter expression.")
private String filterCrs;

@CommandLine.Option(names = {"-s", "--sql-filter"}, paramLabel = "<sql>",
@CommandLine.Option(names = {"--sql-filter"}, paramLabel = "<sql>",
description = "SQL query expression to use as filter.")
private String sqlFilter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package org.citydb.cli.deleter.options;

import org.citydb.cli.common.CountLimitOptions;
import org.citydb.cli.common.FilterOptions;
import org.citydb.cli.common.Option;
import org.citydb.cli.common.TypeNameOption;
Expand All @@ -35,6 +36,9 @@ public class QueryOptions implements Option {
@CommandLine.ArgGroup(exclusive = false)
private FilterOptions filterOptions;

@CommandLine.ArgGroup(exclusive = false)
private CountLimitOptions countLimitOptions;

public Query getQuery() throws FilterParseException {
Query query = new Query();
if (typeNameOption != null) {
Expand All @@ -46,6 +50,17 @@ public Query getQuery() throws FilterParseException {
query.setFilterSrs(filterOptions.getFilterCrs());
}

if (countLimitOptions != null) {
query.setCountLimit(countLimitOptions.getCountLimit());
}

return query;
}

@Override
public void preprocess(CommandLine commandLine) throws Exception {
if (countLimitOptions != null) {
countLimitOptions.preprocess(commandLine);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.citydb.cli.ExecutionException;
import org.citydb.cli.common.*;
import org.citydb.cli.exporter.options.QueryOptions;
import org.citydb.cli.exporter.util.SequentialWriter;
import org.citydb.cli.util.CommandHelper;
import org.citydb.config.Config;
import org.citydb.config.ConfigException;
Expand All @@ -38,6 +39,7 @@
import org.citydb.io.IOAdapterManager;
import org.citydb.io.OutputFileBuilder;
import org.citydb.io.writer.FeatureWriter;
import org.citydb.io.writer.WriteException;
import org.citydb.io.writer.WriteOptions;
import org.citydb.io.writer.options.OutputFormatOptions;
import org.citydb.logging.LoggerManager;
Expand Down Expand Up @@ -107,14 +109,16 @@ protected boolean doExport() throws ExecutionException {
ExportOptions exportOptions = getExportOptions();
WriteOptions writeOptions = getWriteOptions(databaseManager.getAdapter());
writeOptions.getFormatOptions().set(getFormatOptions(writeOptions.getFormatOptions()));
QueryExecutor executor = helper.getQueryExecutor(getQuery(), databaseManager.getAdapter());

Query query = getQuery();
QueryExecutor executor = helper.getQueryExecutor(query, databaseManager.getAdapter());

FeatureStatistics statistics = new FeatureStatistics(databaseManager.getAdapter());
helper.logIndexStatus(Level.INFO, databaseManager.getAdapter());
initialize(exportOptions, writeOptions, databaseManager);

try (OutputFile outputFile = builder.newOutputFile(outputFileOptions.getFile());
FeatureWriter writer = ioAdapter.createWriter()) {
FeatureWriter writer = createWriter(query, ioAdapter)) {
Exporter exporter = Exporter.newInstance();
exportOptions.setOutputFile(outputFile);

Expand All @@ -127,14 +131,15 @@ protected boolean doExport() throws ExecutionException {
logger.trace("Using SQL query:\n{}", () -> helper.getFormattedSql(executor.getSelect(),
databaseManager.getAdapter()));

long sequenceId = 1;
try (QueryResult result = executor.executeQuery()) {
exporter.startSession(databaseManager.getAdapter(), exportOptions);
while (shouldRun && result.hasNext()) {
long id = result.getId();
exporter.exportFeature(id).whenComplete((feature, t) -> {
exporter.exportFeature(id, sequenceId++).whenComplete((feature, t) -> {
if (feature != null) {
try {
writer.write(feature).whenComplete((success, e) -> {
writer.write(feature, (success, e) -> {
if (success == Boolean.TRUE) {
statistics.add(feature);
long count = counter.incrementAndGet();
Expand Down Expand Up @@ -172,6 +177,13 @@ protected boolean doExport() throws ExecutionException {
return shouldRun;
}

private FeatureWriter createWriter(Query query, IOAdapter ioAdapter) throws WriteException {
FeatureWriter writer = ioAdapter.createWriter();
return query.getSorting().isPresent() ?
SequentialWriter.of(writer) :
writer;
}

protected Query getQuery() throws ExecutionException {
try {
return queryOptions != null ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package org.citydb.cli.exporter.options;

import org.citydb.cli.common.CountLimitOptions;
import org.citydb.cli.common.FilterOptions;
import org.citydb.cli.common.Option;
import org.citydb.cli.common.TypeNameOption;
Expand All @@ -35,6 +36,12 @@ public class QueryOptions implements Option {
@CommandLine.ArgGroup(exclusive = false)
private FilterOptions filterOptions;

@CommandLine.ArgGroup(exclusive = false)
private SortingOption sortingOption;

@CommandLine.ArgGroup(exclusive = false)
private CountLimitOptions countLimitOptions;

public Query getQuery() throws FilterParseException {
Query query = new Query();
if (typeNameOption != null) {
Expand All @@ -46,6 +53,21 @@ public Query getQuery() throws FilterParseException {
query.setFilterSrs(filterOptions.getFilterCrs());
}

if (sortingOption != null) {
query.setSorting(sortingOption.getSorting());
}

if (countLimitOptions != null) {
query.setCountLimit(countLimitOptions.getCountLimit());
}

return query;
}

@Override
public void preprocess(CommandLine commandLine) throws Exception {
if (countLimitOptions != null) {
countLimitOptions.preprocess(commandLine);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* citydb-tool - Command-line tool for the 3D City Database
* https://www.3dcitydb.org/
*
* Copyright 2022-2024
* virtualcitysystems GmbH, Germany
* https://vc.systems/
*
* 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.citydb.cli.exporter.options;

import org.citydb.cli.common.Option;
import org.citydb.query.filter.encoding.FilterParseException;
import org.citydb.query.sorting.SortOrder;
import org.citydb.query.sorting.Sorting;
import picocli.CommandLine;

public class SortingOption implements Option {
@CommandLine.Option(names = {"-s", "--sort-by"}, split = ",", paramLabel = "<property[+|-]>", required = true,
description = "Properties and sort orders for sorting features.")
private String[] sortBy;

public Sorting getSorting() throws FilterParseException {
if (sortBy != null) {
Sorting sorting = new Sorting();
for (String sortToken : sortBy) {
if (sortToken.endsWith("+")) {
sorting.addSortBy(sortToken.substring(0, sortToken.length() - 1), SortOrder.ASC);
} else if (sortToken.endsWith("-")) {
sorting.addSortBy(sortToken.substring(0, sortToken.length() - 1), SortOrder.DESC);
} else {
sorting.addSortBy(sortToken, SortOrder.ASC);
}
}

return sorting;
} else {
return null;
}
}
}
Loading

0 comments on commit 63ff50a

Please sign in to comment.