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

Add limit option and sorting to Query API #30

Merged
merged 4 commits into from
Jul 4, 2024
Merged
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
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
Loading