Search in sources :

Example 1 with Filter

use of org.apache.sis.filter.Filter in project sis by apache.

the class FeatureStream method filter.

/**
 * Returns a stream with features of this stream that match the given predicate.
 * If the given predicate is an instance of {@link Filter}, then this method tries
 * to express the filter using SQL statements.
 */
@Override
public Stream<AbstractFeature> filter(final Predicate<? super AbstractFeature> predicate) {
    ArgumentChecks.ensureNonNull("predicate", predicate);
    if (predicate == Filter.include())
        return this;
    if (predicate == Filter.exclude())
        return empty();
    if (isPagined()) {
        /*
             * Offset/limit executed before the filter. Can not continue to build an SQL statement
             * because the SQL `OFFSET ... FETCH NEXT` clause would be executed after the filter.
             */
        return delegate().filter(predicate);
    }
    if (!(predicate instanceof Filter<?>)) {
        hasPredicates = true;
        return super.filter(predicate);
    }
    if (selection == null) {
        selection = new SelectionClause(table);
        filterToSQL = table.database.getFilterToSupportedSQL();
    }
    /*
         * Simplify/optimize the filter (it may cause `include` or `exclude` filters to emerge) and try
         * to convert the filter to SQL statements. This is not necessarily an all or nothing operation:
         * if we have a "F₀ AND F₁ AND F₂" chain, it is possible to have some Fₙ as SQL statements and
         * other Fₙ executed in Java code.
         */
    final Optimization optimization = new Optimization();
    optimization.setFeatureType(table.featureType);
    Stream<AbstractFeature> stream = this;
    for (final Filter<? super AbstractFeature> filter : optimization.applyAndDecompose((Filter<? super AbstractFeature>) predicate)) {
        if (filter == Filter.include())
            continue;
        if (filter == Filter.exclude())
            return empty();
        if (!selection.tryAppend(filterToSQL, filter)) {
            // Delegate to Java code all filters that we can not translate to SQL statement.
            stream = super.filter(filter);
            hasPredicates = true;
        }
    }
    return stream;
}
Also used : Filter(org.apache.sis.filter.Filter) AbstractFeature(org.apache.sis.feature.AbstractFeature) Optimization(org.apache.sis.filter.Optimization)

Example 2 with Filter

use of org.apache.sis.filter.Filter in project sis by apache.

the class SelectionClauseWriter method removeUnsupportedFunctions.

/**
 * Returns a writer without the functions that are unsupported by the database software.
 * If the database supports all functions, then this method returns {@code this}.
 * Otherwise it returns a copy of {@code this} with unsupported functions removed.
 * This method should be invoked at most once for a {@link Database} instance.
 *
 * @param  database  information about the database software.
 * @return a writer with unsupported functions removed.
 */
final SelectionClauseWriter removeUnsupportedFunctions(final Database<?> database) {
    final Map<String, SpatialOperatorName> unsupported = new HashMap<>();
    try (Connection c = database.source.getConnection()) {
        final DatabaseMetaData metadata = c.getMetaData();
        /*
             * Get the names of all spatial functions for which a handler is registered.
             * All those handlers should be instances of `Function`, otherwise we do not
             * know how to determine whether the function is supported or not.
             */
        final boolean lowerCase = metadata.storesLowerCaseIdentifiers();
        final boolean upperCase = metadata.storesUpperCaseIdentifiers();
        for (final SpatialOperatorName type : SpatialOperatorName.values()) {
            final BiConsumer<Filter<AbstractFeature>, SelectionClause> function = getFilterHandler(type);
            if (function instanceof Function) {
                String name = ((Function) function).name;
                if (lowerCase)
                    name = name.toLowerCase(Locale.US);
                if (upperCase)
                    name = name.toUpperCase(Locale.US);
                unsupported.put(name, type);
            }
        }
        /*
             * Remove from above map all functions that are supported by the database.
             * This list is potentially large so we do not put those items in a map.
             */
        final String pattern = (lowerCase ? "st_%" : "ST\\_%").replace("\\", metadata.getSearchStringEscape());
        try (ResultSet r = metadata.getFunctions(database.catalogOfSpatialTables, database.schemaOfSpatialTables, pattern)) {
            while (r.next()) {
                unsupported.remove(r.getString("FUNCTION_NAME"));
            }
        }
    } catch (SQLException e) {
        /*
             * If this exception happens before `unsupported` entries were removed,
             * this is equivalent to assuming that all functions are unsupported.
             */
        database.listeners.warning(e);
    }
    /*
         * Remaining functions are unsupported functions.
         */
    if (unsupported.isEmpty()) {
        return this;
    }
    final SelectionClauseWriter copy = duplicate();
    copy.removeFilterHandlers(unsupported.values());
    return copy;
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) Connection(java.sql.Connection) DatabaseMetaData(java.sql.DatabaseMetaData) SpatialOperatorName(org.apache.sis.internal.geoapi.filter.SpatialOperatorName) Filter(org.apache.sis.filter.Filter) ResultSet(java.sql.ResultSet)

Example 3 with Filter

use of org.apache.sis.filter.Filter in project sis by apache.

the class FeatureSubset method features.

/**
 * Returns a stream of all features contained in this dataset.
 */
@Override
public Stream<AbstractFeature> features(final boolean parallel) throws DataStoreException {
    Stream<AbstractFeature> stream = source.features(parallel);
    /*
         * Apply filter.
         */
    final Filter<? super AbstractFeature> selection = query.getSelection();
    if (selection != null && !selection.equals(Filter.include())) {
        stream = stream.filter(selection);
    }
    /*
         * Apply sorting.
         */
    final SortBy<AbstractFeature> sortBy = query.getSortBy();
    if (sortBy != null) {
        stream = stream.sorted(sortBy);
    }
    /*
         * Apply offset.
         */
    final long offset = query.getOffset();
    if (offset > 0) {
        stream = stream.skip(offset);
    }
    /*
         * Apply limit.
         */
    final OptionalLong limit = query.getLimit();
    if (limit.isPresent()) {
        stream = stream.limit(limit.getAsLong());
    }
    /*
         * Transform feature instances.
         * Note: "projection" here is in relational database sense, not map projection.
         */
    final FeatureQuery.NamedExpression[] projection = query.getProjection();
    if (projection != null) {
        @SuppressWarnings({ "unchecked", "rawtypes" }) final Expression<? super AbstractFeature, ?>[] expressions = new Expression[projection.length];
        for (int i = 0; i < expressions.length; i++) {
            expressions[i] = projection[i].expression;
        }
        final DefaultFeatureType type = getType();
        final String[] names = FeatureUtilities.getNames(type.getProperties(false));
        stream = stream.map(t -> {
            final AbstractFeature f = type.newInstance();
            for (int i = 0; i < expressions.length; i++) {
                f.setPropertyValue(names[i], expressions[i].apply(t));
            }
            return f;
        });
    }
    return stream;
}
Also used : OptionalLong(java.util.OptionalLong) DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) Stream(java.util.stream.Stream) AbstractFeatureSet(org.apache.sis.internal.storage.AbstractFeatureSet) Expression(org.apache.sis.filter.Expression) Resources(org.apache.sis.internal.storage.Resources) FeatureUtilities(org.apache.sis.internal.feature.FeatureUtilities) StoreListeners(org.apache.sis.storage.event.StoreListeners) SortBy(org.apache.sis.internal.geoapi.filter.SortBy) AbstractFeature(org.apache.sis.feature.AbstractFeature) Filter(org.apache.sis.filter.Filter) AbstractFeature(org.apache.sis.feature.AbstractFeature) Expression(org.apache.sis.filter.Expression) DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) OptionalLong(java.util.OptionalLong)

Aggregations

Filter (org.apache.sis.filter.Filter)3 AbstractFeature (org.apache.sis.feature.AbstractFeature)2 Connection (java.sql.Connection)1 DatabaseMetaData (java.sql.DatabaseMetaData)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 HashMap (java.util.HashMap)1 OptionalLong (java.util.OptionalLong)1 Stream (java.util.stream.Stream)1 DefaultFeatureType (org.apache.sis.feature.DefaultFeatureType)1 Expression (org.apache.sis.filter.Expression)1 Optimization (org.apache.sis.filter.Optimization)1 FeatureUtilities (org.apache.sis.internal.feature.FeatureUtilities)1 SortBy (org.apache.sis.internal.geoapi.filter.SortBy)1 SpatialOperatorName (org.apache.sis.internal.geoapi.filter.SpatialOperatorName)1 AbstractFeatureSet (org.apache.sis.internal.storage.AbstractFeatureSet)1 Resources (org.apache.sis.internal.storage.Resources)1 StoreListeners (org.apache.sis.storage.event.StoreListeners)1