Overview Readers that are spatially enabled have a value of "Always" or "Optional" in the Spatial Index entry of their Quick Facts table. For readers with a value of Optional, you can use IUniversalReader::getProperties() to determine whether a spatial index is available for a particular dataset. Spatially enabled readers are often used to access datasets with millions of features. For this reason, FME Objects users are discouraged from creating a reader cache for spatially enabled readers because caching this much data is not practical. Also, these types of readers usually have optimized query capabilities that FME should take advantage of. Developers of all spatially enabled readers must therefore implement the following three public reader methods: - spatialEnabled() which must return FME_TRUE. - getProperties() which identifies which setConstraints() types are supported by returning an attributed feature. - setConstraints() which must pass the correct corresponding queries to the database based on the provided constraint type. Constraints are specified as attributes on an IFMEFeature object, the constraint feature, which is passed to setConstraints as an input parameter. The name of the attribute used to specify the type of constraint to be used is fme_search_type. The following table describes the different values supported for fme_search_type: fme_all_features Retrieve features based on specific attribute value or feature type value fme_envelope_intersects Retrieve features whose bounding box intersects a rectangular selection area fme_envelope_ids Retrieve the IDs for features whose bounding box intersects a rectangular selection area fme_nonspatial_ids Retrieve the IDs for non-spatial features fme_feature_type_ids Retrieve the IDs for all features, by feature type. This can be used along with the specified-feature constraints to retrieve only features from certain feature types. fme_closest Retrieve the feature that is closest to a selection point, within a maximum distance threshold fme_specified_feature Retrieve a specific feature by index fme_specified_feature_list Retrieve a list of specific features by index fme_specified_feature_range Retrieve a range of features based on a start and end index fme_execute_sql Retrieve result features from executing the provided custom SQL statement fme_schema_from_query Retrieve schema features as described by provided custom database query fme_db_join Retrieve attribute only features for the specified Relate call defined by attributes on the constraint feature fme_metadata Retrieve metadata about specified feature types in a dataset fme_get_version_list Retrieve data about all the versions that a user has access to fme_get_historical_version_list Retrieve data about all the versions that a user has access to fme_spatial_interaction Retrieve features which satisfy a given spatial interaction There are three special constraint primitives that are supported across several of these search types: - The fme_where attribute is used to pass a WHERE clause directly to the database. - The fme_feature_type list attribute is used to retrieve only features with specific feature types. If this is not present, then database readers should return no features while file readers should return features from all feature types. - It has been common for formats (see dll_fme_ado) to support both lists and plain fme_feature_type attributes when only lists are officially supported. This is discouraged going forward. - Some formats require fme_feature_type when they really shouldn't. For example, dll_fme_ado will not process constraints unless an fme_feature_type is provided. Any setConstraints client that operates on arbitrary formats should pass a placeholder fme_feature_type to ALL setConstraints calls. - The fme_type list attribute is used to retrieve only features with specific fme types. If this is not present, all fme types should be returned. These should be the style of fme type, not fme geometry, and not the format specific type, like "fme_line", "fme_text", "fme_point", and "fme_area". Example: fme_type{0} = fme_line, fme_type{1} = fme_area - Non-list fme_type attributes (such as those set when query geometry is specified) must be ignored Note: The syntax of the WHERE clause is specific to the spatially enabled reader. Sometimes there is an overlap between what the setConstraints specification can express and what reader-specific directives and DEF lines can express. For example, the MSSQL_ADO reader has a WHERE_CLAUSE directive and the constraint feature has an fme_where attribute. There are many other examples. If setConstraints() is called, the reader is essentially reset and the constraint feature takes precedence for all such settings. - The constraint feature takes precedence irrespective of whether setConstraints() is called before or after open(). The order of the setConstraints() and open() calls does not effect semantics. - The constraint feature always takes precedence even for attributes that aren't set. For example, if the reader has a WHERE_CLAUSE directive and setConstraints() is called, the reader-level WHERE_CLAUSE is not used even if the constraint feature doesn't have an fme_where attribute. Also, a constraint feature without fme_feature_types always returns nothing (for database formats; see above). - If setConstraints() is called, it overrides all other settings that relate to constraints. For example, if there is a feature-type-level where clause on a DEF line, setConstraints() overrides it. Also, if there is a feature-type-level custom SQL statement, setConstraints() overrides it. This means that you can't specify feature type FOO as "select * from BAR" and then do an envelope query (or any other constraint) on feature type FOO. - If setConstraints() is called multiple times, each invocation must replace or remove the constraints set by previous invocations. Sometimes it is desirable to use the UniversalReader's implementation of setConstraints() instead of the native reader's implementation, especially if a cache file is used. - If the constraint feature contains an attribute named fme_disable_native_constraints_support, then setConstraints() will not be called on the reader. Instead, constraints will only be applied by the UniversalReader. - The value of the fme_disable_native_constraints_support attribute is ignored. fme_all_features The fme_all_features search type supports the fme_where, fme_type{} and fme_feature_type{} primitives. Additionally, filtering the set of attributes returned can be done using either fme_attribute_list{} when formats can return columns by name, or fme_start_attribute_index and fme_end_attribute_index for sequential column formats such as CSV or Excel. Both attributes expect a numeric, zero indexed value and are honored inclusively. Similar values can be used to limit the features returned as well; fme_start_feature_index and fme_end_feature_index. For example, the following constraint feature: Intent: fme_search_type = fme_all_features (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) fme_where = 'Direction = "North"' (optional) fme_start_attribute_index = 0 (optional) fme_end_attribute_index = 4 (optional) fme_start_feature_index = 11 (optional) fme_end_feature_index = 20 (optional) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); fmeFeature->setAttribute("fme_search_type", "fme_all_features"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setAttribute("fme_where", "Direction = 'North'"); fmeFeature->setAttribute("fme_start_attribute_index", 0); fmeFeature->setAttribute("fme_end_attribute_index", 4); fmeFeature->setAttribute("fme_start_feature_index", 11); fmeFeature->setAttribute("fme_end_feature_index", 20); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_all_features' Attribute(string): `fme_where' has value `Direction = 'North Attribute(32 bit integer): `fme_start_attribute_index' has value `0' Attribute(32 bit integer): `fme_end_attribute_index' has value `4' Attribute(32 bit integer): `fme_start_feature_index' has value `11' Attribute(32 bit integer): `fme_end_feature_index' has value `20' Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Geometry Type: Unknown (0) =========================================================================== retrieves the 11th to 20th feature, inclusive, from the Roads and Railroad feature types, for which the attribute "Direction" has a value of "North", but only retrieves the first 5 attributes. If fme_feature_type{} is not present, and the format is NOT a database format, all feature types are implied. If fme_feature_type{} is not present and the format is a database format, then no feature types are returned. The feature types specified override the IDs originally specified when opening the reader (i.e. no intersection with the original IDs or anything like that). If fme_where is not present, all features from the requested feature types are selected. fme_where is compatible with fme_start_feature_index, fme_end_feature_index fme_start_attribute_index and fme_end_attribute_index. The where clause will be applied first, if supported, then the filtered results will be limited by the supplied indexes. If fme_attribute_list{} is present then the resultant feature will be only return the provided attributes. This acts as an attribute filter. This filter is optional and otherwise all attributes will be returned. This should be used for arbitrary column filtering by name. This is not compatible with the fme_start_attribute_index and fme_end_attribute_index filters. If a format uses ordered, sequential columns such as CSV or Excel, fme_start_attribute_index and fme_end_attribute_index can be used to limit the attributes returned. Both values are numeric, zero indexed and are inclusive. These filters will be applied after the other filters such as fme_where are applied. This is not compatible with the fme_attribute_list{} filter. These filters can also be used individually to limit only the start attribute or end attribute column if desired. If a fme_start_feature_index and fme_end_feature_index are specified they can be used to limit the features returned by feature index. Both values are numeric, zero indexed and are inclusive. These filters will be applied after the other filters such as fme_where are applied. These filters can also be used individually to limit only the start feature or end feature if desired. fme_all_schemas The fme_all_schemas search type supports the fme_feature_type{} primitive. For example, the following constraint feature: Intent: fme_search_type = fme_all_schemas(required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); fmeFeature->setAttribute("fme_search_type", "fme_all_schemas"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_all_schemas' Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Geometry Type: Unknown (0) =========================================================================== retrieves the schema features for the Roads and Railroad feature types. If fme_feature_type{} is not present, and the format is NOT a database format, all feature types are implied. If fme_feature_type{} is not present and the format is a database format, then no feature types are returned. The feature types specified override the IDs originally specified when opening the reader (i.e. no intersection with the original IDs or anything like that). Schema features returned are the same as if the user had called readSchema directly but allow for the reuse of the same instance of the reader. fme_envelope_intersects If getProperties() claims support for fme_envelope_intersects, it will be assumed by FME that the format also has native search envelope support in terms of the settings box. The fme_envelope_intersects search type supports the fme_where, fme_type{} and fme_feature_type{} primitives. If there is an fme_envelope_order_results attribute on the constraint feature with a value of "YES", retrieved features must be ordered according to their distance from the query envelope centroid. Requests for ordered results are honored only if 200 or fewer features intersect the query envelope. The fme_envelope_intersects search type also allows for fme_envelope_width_in_pixels and fme_envelope_height_in_pixels primitives specified as integer attributes on the constraint feature. These are used by the Data Inspector to help formats determine resolutions or zoom levels by contrasting the envelope geometry of the constraint feature to the pixel size attributes above. These are both optionally specified and optionally honored. Currently Stamen, MapBox and ArcGIS Online readers should honor these constraint primitives. The values are in screen pixels and may be buffered based on the graphics view window in the Data Inspector. Readers are expected to take the bounding box of the constraint geometry (which could be as simple a single point) to create an envelope (which might have no length on one or more axes). Readers that support reading from multiple geometry sources (eg columns) should apply envelopes in an OR fashion: A feature matches an envelope if any component geometry matches the envelope, and all geometry will be returned if any component matches the envelope. For example, the following constraint retrieves the features from the Roads and Railroad feature types, for which the attribute "Direction" has a value of "South", and whose linear or polygon geometry intersects with the envelope area defined by (x=0, y=0), (x=100, y=100). Intent: fme_search_type = fme_envelope_intersects (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) fme_where = "Direction = 'South'" (optional) fme_type = {"fme_line", "fme_polygon"} (optional) geometry = {(x=0, y=0), (x=100, y=100)} (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); IFMEStringArray *fmeGeometryTypes = fmeSession->createStringArray(); fmeGeometryTypes->append("fme_line"); fmeGeometryTypes->append("fme_polygon"); fmeFeature->setAttribute("fme_search_type", "fme_envelope_intersects"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setAttribute("fme_where", "Direction = 'South'"); fmeFeature->setAttribute("fme_type", *fmeGeometryTypes); fmeFeature->addCoordinate(0,0); fmeFeature->addCoordinate(100,100); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeGeometryTypes); fmeGeometryTypes = NULL; fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_envelope_intersects' Attribute(string): `fme_type{0}' has value `fme_line' Attribute(string): `fme_type{1}' has value `fme_polygon' Attribute(string): `fme_where' has value `Direction = 'South Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Attribute: `fme_type{0}' is sequenced Attribute: `fme_type{1}' is sequenced Geometry Type: Unknown (0) Number of Coordinates: 2 -- Coordinate Dimension: 2 -- Coordinate System: `' (0,0) (100,100) =========================================================================== fme_envelope_ids The fme_envelope_ids search type does not return a subset of regular reader features. Most other search types pare down the results set returned, offering anything from all features, to envelopes of features, to features given a specific query or where clause. fme_envelope_ids is used to provide a non-regular reader feature that has been formatted specifically to hold a set of matching feature IDs for the dataset or a specific set of feature types. The envelope ids constraint feature and returned features are described below. Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. This step is a post process that uses the IDs of the features returned from the underlying "fme_envelope_intersects" to efficiently allow the Universal Reader to return a list of IDs for future use without building and returning the features themselves. The fme_envelope_id_list is populated as a space delimited list of ids on the output feature. Incremental consecutive IDs are compressed using '-' to improve efficiency, for instance, "1 2 3 4 5 6 7 9" would be represented as "1-7 9". One feature will be returned for each feature type. The fme_envelope_ids search type supports the fme_where, fme_type{} and fme_feature_type{} primitives. Readers that support reading from multiple geometry sources (eg columns) should apply envelopes in an OR fashion: A feature matches an envelope if any component geometry matches the envelope, and all geometry will be returned if any component matches the envelope. For example, the following constraint retrieves the features from the Roads and Railroad feature types, for which the attribute "Direction" has a value of "South", and whose linear or polygon geometry intersects with the envelope area defined by (x=0, y=0), (x=100, y=100). The primary use of this is to improve the performance for the Data Inspector. Intent: fme_search_type = fme_envelope_ids (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) fme_where = "Direction = 'South'" (optional) fme_type = {"fme_line", "fme_polygon"} (optional) geometry = {(x=0, y=0), (x=100, y=100)} (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); IFMEStringArray *fmeGeometryTypes = fmeSession->createStringArray(); fmeGeometryTypes->append("fme_line"); fmeGeometryTypes->append("fme_polygon"); fmeFeature->setAttribute("fme_search_type", "fme_envelope_ids"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setAttribute("fme_where", "Direction = 'South'"); fmeFeature->setAttribute("fme_type", *fmeGeometryTypes); fmeFeature->addCoordinate(0,0); fmeFeature->addCoordinate(100,100); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeGeometryTypes); fmeGeometryTypes = NULL; fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_envelope_ids' Attribute(string): `fme_type{0}' has value `fme_line' Attribute(string): `fme_type{1}' has value `fme_polygon' Attribute(string): `fme_where' has value `Direction = 'South Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Attribute: `fme_type{0}' is sequenced Attribute: `fme_type{1}' is sequenced Geometry Type: Unknown (0) Number of Coordinates: 2 -- Coordinate Dimension: 2 -- Coordinate System: `' (0,0) (100,100) =========================================================================== Envelope IDs feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Road' Attribute(string) : `fme_envelope_id_list' has value `10 9 8 7 6 5' Attribute(string) : `fme_geometry' has value `fme_undefined' Attribute(string) : `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Railroad' Attribute(string) : `fme_envelope_id_list' has value `1-6 8 10' Attribute(string) : `fme_geometry' has value `fme_undefined' Attribute(string) : `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== fme_nonspatial_ids The fme_nonspatial_ids search type does not return a subset of regular reader features. Most other search types pare down the results set returned, offering anything from all features, to envelopes of features, to features given a specific query or where clause. fme_nonspatial_ids is used to provide a non-regular reader feature that has been formatted specifically to hold a set of matching feature IDs for the dataset or a specific set of feature types. The non-spatial ids constraint feature and returned features are described below. Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. This step is a post process that uses the IDs of the features to efficiently allow the Universal Reader to return a list of IDs for future use without building and returning the features themselves. The fme_nonspatial_id_list is populated as a space delimited list of ids on the output feature. One feature will be returned for each feature type. For example, the following constraint retrieves the features from the Roads and Railroad feature types. The primary use of this is to improve the performance for the Data Inspector. Intent: fme_search_type = fme_nonspatial_ids (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); fmeFeature->setAttribute("fme_search_type", "fme_nonspatial_ids"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_nonspatial_ids' Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Geometry Type: Unknown (0) =========================================================================== Non-spatial IDs feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Road' Attribute(string): `fme_geometry' has value `fme_undefined' Attribute(string): `fme_nonspatial_id_list' has value `0 1' Attribute(string): `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Railroad' Attribute(string): `fme_geometry' has value `fme_undefined' Attribute(string): `fme_nonspatial_id_list' has value `3 6 9' Attribute(string): `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== fme_feature_type_ids The fme_feature_type_ids search type does not return a subset of regular reader features. Most other search types pare down the results set returned, offering anything from all features, to envelopes of features, to features given a specific query or where clause. fme_feature_type_ids is used to provide a non-regular reader feature that has been formatted specifically to hold a set of matching feature IDs for the dataset or a specific set of feature types. Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. This step is a post process that uses the IDs of the features to efficiently allow the Universal Reader to return a list of IDs for future use without building and returning the features themselves. The fme_feature_type_ids is populated as a space delimited list of ids on the output feature. One feature will be returned for each feature type. For example, the following constraint retrieves the features from the Roads and Railroad feature types. The primary use of this is to improve the performance for the Data Inspector. Intent: fme_search_type = fme_feature_type_ids (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); fmeFeature->setAttribute("fme_search_type", "fme_feature_type_ids"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_feature_type{1}' has value `Railroad' Attribute(string): `fme_search_type' has value `fme_feature_type_ids' Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Geometry Type: Unknown (0) =========================================================================== Feature Type IDs feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Road' Attribute(string): `fme_geometry' has value `fme_undefined' Attribute(string): `fme_feature_type_id_list' has value `0 1' Attribute(string): `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Railroad' Attribute(string): `fme_geometry' has value `fme_undefined' Attribute(string): `fme_feature_type_id_list' has value `3 6 9' Attribute(string): `fme_type' has value `fme_no_geom' Coordinate System: `LL-WGS84' Geometry Type: IFMENull =========================================================================== fme_closest Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. The fme_closest search type supports the fme_where, fme_type{} and fme_feature_type{} primitive constraints. If the constraint feature geometry has only one coordinate, that coordinate is used as the query point; otherwise the centroid of the constraint feature's bounding box is used as the query point. When a maximum distance threshold is specified using the fme_max_distance attribute, only the closest feature will only be retrieved if the distance between it and the query point is less than fme_max_distance; otherwise no feature is retrieved. For example, the following constraint retrieves the feature from the Roads and Railroad feature types that is the closest point to the point (x=10, y=10), only if its "Direction" attribute has a value of "North", and it is within 100.0 ground coordinates; otherwise no feature is retrieved. Intent: fme_search_type = fme_closest (required) fme_feature_type = {"Road","Railroad"} (recommended 1..M) fme_where = "Direction = 'North'" (optional) fme_type = {"fme_point"} (optional) fme_max_distance = 100.0; (recommended) geometry = {(x=10, y=10)} (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeatureTypes->append("Railroad"); IFMEStringArray *fmeGeometryTypes = fmeSession->createStringArray(); fmeGeometryTypes->append("fme_point"); FME_Real64 maxDistance = 100.0; fmeFeature->setAttribute("fme_search_type", "fme_closest"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setAttribute("fme_where", "Direction = 'North'"); fmeFeature->setAttribute("fme_type", *fmeGeometryTypes); fmeFeature->setAttribute("fme_max_distance", maxDistance); fmeFeature->addCoordinate(10,10); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeGeometryTypes); fmeGeometryTypes = NULL; fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string) : `fme_feature_type{0}' has value `Road' Attribute(string) : `fme_feature_type{1}' has value `Railroad' Attribute(64 bit real): `fme_max_distance' has value `100.0' Attribute(string) : `fme_search_type' has value `fme_closest' Attribute(string) : `fme_type{0}' has value `fme_point' Attribute(string) : `fme_where' has value `Direction = 'North Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_feature_type{1}' is sequenced Attribute: `fme_type{0}' is sequenced Geometry Type: Unknown (0) Number of Coordinates: 1 -- Coordinate Dimension: 1 -- Coordinate System: `' (10,10) =========================================================================== fme_specified_feature Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. For example the following constraint retrieves the 10th feature of the dataset: Intent: fme_search_type = fme_specified_feature (required) fme_index = 10 (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); FME_Int32 index = 10; fmeFeature->setAttribute("fme_search_type", "fme_specified_feature"); fmeFeature->setAttribute("fme_index", index); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string) : `fme_feature_type' has value `Road' Attribute(32 bit integer): `fme_index' has value `10' Attribute(string) : `fme_search_type' has value `fme_specified_feature' Geometry Type: Unknown (0) =========================================================================== fme_specified_feature_list Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. For example the following constraint retrieves a list of features from the dataset: Intent: fme_search_type = fme_specified_feature_list (required) fme_index_list = "2 34 78 21 95" (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); FMEObsoleteStringImp indexList = "2 34 78 21 95"; fmeFeature->setAttribute("fme_search_type", "fme_specified_feature_list"); fmeFeature->setAttribute("fme_index_list", indexList); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string) : `fme_feature_type' has value `Road' Attribute(string) : `fme_index_list' has value `2 34 78 21 95' Attribute(string) : `fme_search_type' has value `fme_specified_feature_list' Geometry Type: Unknown (0) =========================================================================== fme_specified_feature_range Implemented entirely by the Universal Reader, and will never be passed to an IFMEReader. For example the following constraint retrieves features 10-20 from the dataset: Intent: fme_search_type = fme_specified_feature_range (required) fme_start_index = 10 (required) fme_end_index = 20 (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); FME_Int32 startIndex = 10; FME_Int32 endIndex = 20; fmeFeature->setAttribute("fme_search_type", "fme_specified_feature_range"); fmeFeature->setAttribute("fme_start_index", startIndex); fmeFeature->setAttribute("fme_end_index", endIndex); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string) : `fme_feature_type' has value `Road' Attribute(32 bit integer): `fme_start_index' has value `10' Attribute(32 bit integer): `fme_end_index' has value `20' Attribute(string) : `fme_search_type' has value `fme_specified_feature_range' Geometry Type: Unknown (0) =========================================================================== fme_execute_sql fme_execute_sql is the setConstraints fme_search_type used to support arbitrary SQL statement execution such as those passed by the SqlExecutor and SqlCreator transformers in FME. Since there is no specific list of tables to be queried, but rather the SQL statement itself, this search type does not support fme_feature_type in the same way that other search types do. The SQL query is free form SQL, and specific function implementation depends on the underlying reader and format. The special attribute used on fme_execute_sql type constraint features to specify the SQL statement is called fme_sql_statement. For example, the following constraint feature: Intent: fme_feature_type = placeholder_value (optional for well behaved formats) fme_search_type = fme_execute_sql (required) fme_sql_statement = select * from mytable where id < 10 (required) Code: fmeFeature->resetFeature(); fmeFeature->setAttribute("fme_feature_type", "placeholder_value"); fmeFeature->setAttribute("fme_search_type", "fme_execute_sql"); fmeFeature->setAttribute("fme_sql_statement", "select * from mytable where id < 10"); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `' Attribute(string): `fme_feature_type' has value `placeholder_value' Attribute(string): `fme_search_type' has value `fme_execute_sql' Attribute(string): `fme_sql_statement' has value `select * from mytable where id < 10' Geometry Type: Unknown (0) =========================================================================== The constraint feature instructs the reader to return one feature per row in the result set (database) or record (file). SQL commands can also be run but do not return a result set. In this case a call to reader.read() is still required to execute the SQL statement but the feature returned (if any) can be discarded. Transaction Control fme_execute_sql statements should not be committed until either the setConstraints client sends a COMMIT statement (not be interpreted by the reader, but passed on to the database), a non- fme_execute_sql setConstraints is requested, or the reader is closed. For example: 1. fme_execute_sql1 INSERT ... 2. fme_all_features <commit for changing modes> 3. fme_execute_sql2 INSERT ... 4. fme_execute_sql3 COMMIT <client requested commit> 5. fme_execute_sql4 INSERT ... 6. <commit on reader close> We should be autocommitting in all non-fme_execute_sql modes, to avoid holding locks on tables. The importance of this depends greatly on the locking behavior of the underlying database (it's a big deal if no one can write if read locks are present). fme_schema_from_query fme_schema_from_query is the setConstraints fme_search_type used to support getting result schema from arbitrary database queries, for example those passed by the SqlExecutor and SqlCreator transformers in FME. This will not execute the query, but rather describe the schema of the query's result set. Since there is no specific list of tables to be queried, but rather the query statement itself, this search type does not support fme_feature_type in the same way that other search types do. The query is free form, and specific function implementation depends on the underlying reader and format. To specify the query, a special attribute called fme_sql_statement is used on fme_schema_from_query type constraint features. For example, the following constraint feature: Intent: fme_feature_type = placeholder_value (optional for well behaved formats) fme_search_type = fme_schema_from_query (required) fme_sql_statement = select first_name, last_name, id from mytable where id < 10 (required) Code: fmeFeature->resetFeature(); fmeFeature->setAttribute("fme_feature_type", "placeholder_value"); fmeFeature->setAttribute("fme_search_type", "fme_schema_from_query"); fmeFeature->setAttribute("fme_sql_statement", "select first_name, last_name, id from mytable where id < 10"); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `' Attribute(string): `fme_feature_type' has value `placeholder_value' Attribute(string): `fme_search_type' has value `fme_schema_from_query' Attribute(string): `fme_sql_statement' has value `select first_name, last_name, id from mytable where id < 10' Geometry Type: Unknown (0) =========================================================================== Schema Feature Returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `placeholder_value' Attribute(string): `first_name' has value `varchar2(50)' Attribute(string): `last_name' has value `varchar2(50)' Attribute(string): `id' has value `integer' Attribute: `first_name' is sequenced Attribute: `last_name' is sequenced Attribute: `id' is sequenced Geometry Type: Unknown (0) =========================================================================== The constraint feature instructs the reader to return one schema feature describing the result set (database) or record (file). The returned schema feature's attribute names correspond to column names as described by the result set, and the attribute values describe the corresponding column's data type. The attributes are sequenced in the same order as columns described by the result set. Some SQL commands (eg. DDL) do not return a result set, and so do not have a schema. In this case a call to reader.read() will return a feature with no schema information. fme_db_join The fme_db_join is the setConstraints fme_search_type used to support the Joiner transformer. This search type supports fme_feature_type{} primitive but only uses the first entry. The transfer columns, key columns, and key values parameters are passed on the constraint feature using string arrays named fme_select_columns{}, fme_key_columns{} and fme_key_values{} respectively. Even though it only makes sense to supply one feature type name in the fme_feature_type{} for this constraint type it is still exposed as a list attribute for consistency. If more than one feature type is specified then only the first is used. It is possible that a table column's values contains trailing spaces, which would likely cause the join to fail if the key does not contain the same trailing spaces. Supplying fme_trim_keys with a value of yes tells supported readers to perform trimming of the column values so that the values will match the corresponding rows of the table. For example, the following constraint: Intent: fme_search_type = fme_db_join (required) fme_feature_type = {"Road"} (required) fme_select_columns = "id" "name" "numlanes" (required) fme_key_columns = "id" "name" (required) fme_key_values = "23" "straight" (required) fme_trim_keys = "yes" (optional) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); IFMEStringArray *fmeSelectColumns = fmeSession->createStringArray(); fmeSelectColumns->append("id"); fmeSelectColumns->append("name"); fmeSelectColumns->append("numlanes"); IFMEStringArray *fmeKeyColumns = fmeSession->createStringArray(); fmeKeyColumns->append("id"); fmeKeyColumns->append("name"); IFMEStringArray *fmeKeyValues = fmeSession->createStringArray(); fmeKeyValues->append("23"); fmeKeyValues->append("straight"); fmeFeature->setAttribute("fme_search_type", "fme_db_join"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setListAttribute("fme_select_columns", *fmeSelectColumns); fmeFeature->setListAttribute("fme_key_columns", *fmeKeyColumns); fmeFeature->setListAttribute("fme_key_values", *fmeKeyValues); fmeFeature->setAttribute("fme_trim_keys", "yes"); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeKeyValues); fmeKeyValues = NULL; fmeSession->destroyStringArray(fmeKeyColumns); fmeKeyColumns = NULL; fmeSession->destroyStringArray(fmeSelectColumns); fmeSelectColumns = NULL; fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_key_columns{0}' has value `id' Attribute(string): `fme_key_columns{1}' has value `name' Attribute(string): `fme_key_values{0}' has value `23' Attribute(string): `fme_key_values{1}' has value `straight' Attribute(string): `fme_search_type' has value `fme_db_join' Attribute(string): `fme_select_columns{0}' has value `id' Attribute(string): `fme_select_columns{1}' has value `name' Attribute(string): `fme_select_columns{2}' has value `numlanes' Attribute(string): `fme_trim_keys' has value `yes' Attribute: `fme_feature_type{0}' is sequenced Attribute: `fme_key_columns{0}' is sequenced Attribute: `fme_key_columns{1}' is sequenced Attribute: `fme_key_values{0}' is sequenced Attribute: `fme_key_values{1}' is sequenced Attribute: `fme_select_columns{0}' is sequenced Attribute: `fme_select_columns{1}' is sequenced Attribute: `fme_select_columns{2}' is sequenced Geometry Type: Unknown (0) =========================================================================== The constraint feature above results in the attributes id, name and numlanes being placed on the feature where the id = 23 the name = "straight". One feature is returned per matching row in the database. Any trailing spaces on the "name" column values of the database table are not considered significant when comparing with the given value ("straight"). fme_metadata The fme_metadata search type does not return a subset of regular reader features. Most other search types pare down the results set returned, offering anything from all features, to envelopes of features, to features given a specific query or where clause. fme_metadata is used to provide a non-regular reader feature that has been formatted specifically to hold well-defined metadata attributes about a given feature type. The metadata constraint feature and returned metadata feature are described below. The fme_metadata search type supports fme_feature_type{} primitive and will return one metadata feature per feature type specified. If the fme_feature_type{} primitive is not specified, then one metadata feature will be returned per feature type on the dataset. If the only attributes specified on the query feature are fme_search_type and fme_feature_type{} (or just fme_search_type), then all the metadata attributes are returned. Otherwise, only the specific information requested is returned on the metadata feature. To request that a metadata feature contain a certain attribute, set the attribute on the query feature. It doesn't matter what value is given to the attribute, or even if a value is given at all. For example, the following constraint: Intent: fme_search_type = fme_metadata (required) fme_feature_type = {"Road"} (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeature->setAttribute("fme_search_type", "fme_metadata"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_feature_type{0}' has value `Road' Attribute(string): `fme_search_type' has value `fme_metadata' Attribute: `fme_feature_type{0}' is sequenced Geometry Type: Unknown (0) =========================================================================== Metadata feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `Road' Attribute(string) : `fme_contains_spatial_column' has value `yes' Attribute(string) : `fme_coordinate_system{0}' has value `LL-83' Attribute(string) : `fme_dimension' has value `2' Attribute(string) : `fme_feature_identifier' has value `oid' Attribute(string) : `fme_cache_file_name' has value `c:\temp\temp.ffs' Attribute(string) : `fme_geometry' has value `fme_polygon' Attribute(string) : `fme_geometry{0}' has value `fme_point' Attribute(string) : `fme_geometry{1}' has value `fme_line' Attribute(64 bit unsigned integer): `fme_geometry_class' has value `32' Attribute(64 bit real) : `fme_max_x' has value `100.0' Attribute(64 bit real) : `fme_max_y' has value `100.0' Attribute(64 bit real) : `fme_min_x' has value `0.0' Attribute(64 bit real) : `fme_min_y' has value `0.0' Attribute(32 bit unsigned integer): `fme_num_entries' has value `324' Attribute(string) : `fme_type' has value `fme_area' Geometry Type: Polygon (4) Number of Coordinates: 5 -- Coordinate Dimension: 2 -- Coordinate System: `LL-83' (0.0,0.0) (0.0,100.0) (100.0,100.0) (100.0,0.0) (0.0,0.0) =========================================================================== However, if all that one wanted returned on a metadata feature were the extents, coordinate system, and the number of features for that feature type, then the code would look like: Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("Road"); fmeFeature->setAttribute("fme_search_type", "fme_metadata"); fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); fmeFeature->setAttribute("fme_extents"); fmeFeature->setAttribute("fme_coordinate_system"); fmeFeature->setAttribute("fme_num_entries"); fmeReader->setConstraints(*fmeFeature); fmeSession->destroyStringArray(fmeFeatureTypes); fmeFeatureTypes = NULL; - The feature type of the returned metadata feature specifies the feature type for which the metadata applies. - fme_contains_spatial_column indicates whether the feature type contains a geometry column. For example in a database it may be a BLOB or Long Binary column. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_contains_spatial_column should be on the query feature. - fme_dimension is the dimension of the feature type - either 2 or 3. If the format does not restrict the dimension of the feature in a feature type, this should be set to 3D. If the feature type is simply tabular data, then this attribute should not be set on the feature. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_dimension should be on the query feature. - fme_geometry is the string array list of possible geometries in the feature type. They may not all exist. For some formats this is only one entry. The elements in this list should be fme_types, not the format specific geometry and not fme_geometry values - yes, the name is misleading. The possible fme_types are as follows: "fme_point" (kFME_point constant), "fme_arc" (kFME_arc constant), "fme_ellipse" (kFME_ellipse constant), "fme_text" (kFME_text constant), "fme_line" (kFME_line constant), "fme_area" (kFME_area constant), "fme_raster" (kFME_raster constant), "fme_collection" (kFME_collection constant), "fme_surface" (kFME_surface constant), "fme_solid" (kFME_solid constant), and "fme_no_geom" (kFME_no_geom constant). The constants are found in FME_HOME/fmeobjects/cpp/fmereaderconstants.h. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_geometry should be on the query feature (it doesn't matter if it's a list attribute or a regular attribute). Note that readSchema() expects fme_geometry to be populated with format_ types, not fme_ types. Unclear how this confusing discrepancy came about, although the setConstraints() choice seems stronger. - fme_num_entries is the number of features in the feature type. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_num_entries should be on the query feature. Even if this is an expensive call, this should be implemented. If one do not want this attribute returned, then one should be specific in which attributes one wants returned. - fme_feature_identifier is a column which may act as a unique index for the feature type. The column must: * Contain unique 32 bit (or less) unsigned integers * Most formats will return signed columns with the assumption that they will not contain numbers below zero. PR#19555 * Not contain nulls * Most formats implement this by returning a column with a non-nullable constraint. * PostgreSQL based formats scan the column to ensure no nulls exist. This is arguably better because it increases the number of candidate columns, or worse because the data could change underneath, invalidating the choice. * Be reference-able without quoting * "WHERE myidcol = x" must be valid. * PR#58632: Many formats are not following this rule, resulting in a poor column being chosen and no data being returned for each feature in ArcCatalog Tabular Preview. * PR#58633: If DataInterop moves to preferring fme_db_join queries over fme_all_features + fme_where, we will be able to work around this limitation on a format by format basis (by implementing fme_db_join). * Support fast queries * Most formats will return an indexed column. This is not necessary for formats that support massively parallel row scans. This attribute should not be set if such a column does not exist. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_feature_identifier should be on the query feature. This is unrelated to the fme_specified_feature search type; callers typically use the returned value with generated fme_where clauses. - fme_coordinate_system is the coordinate system string containing the FME coordinate system name of the current feature type. User defined coordinate system values will be returned if FME does not have a predefined coordinate system. E.g. sometimes we get the name as '_fme_01' for the coordinate system from the coordinate system manager. If the feature type does not have a coordinate system associated with it, then the coordinate system should not be set. The fme_coordinate_system value may be returned as a string or a string array list of FME coordinate system name(s). If one wants only a subset of metadata attributes returned and the coordinate system is part of that subset, then the attribute fme_coordinate_system should be on the query feature. - fme_geometry_class is a single bit mask representing the geometries of the current feature type. The representation of each geometry is defined in the FME_GeometryTypeMask enum found in FME_HOME/fmeobjects/cpp/fmereaderconstants.h. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_geometry_class should be on the query feature (it doesn't matter if it's a list attribute or a regular attribute). - The extents of the feature type are specified as five points, and are returned on the feature as min and max attributes and as the feature's geometry, expressed as a polygon (see the example feature above). Note that in some readers the bounds (which is the smallest polygon that can completely encompass all the features) rather than the extents are returned. If the feature type is 2D then no z values should be set. Point 1: minx, miny, minz Point 2: minx, maxy, minz Point 3: maxx, maxy, maxz Point 4: maxx, miny, maxz Point 5: minx, miny, minz - Degenerate bounding box cases are handled exactly the same, i.e the bounding box is a point or a line (minx = maxx). - The extents and the min/max attributes should not be set when: 1. the reader returns the bounds rather than the extents, and: 1. the feature type doesn't contain any features but allows storage of spatial features 2. the feature type allows spatial features and contains features, but none of the features have geometry - for example, one has a database table that contains a spatial column and contains records in the table; however, all the records have set the spatial column to NULL 2. the feature type doesn't allow storage of spatial features. - fme_cache_file_name is the cached FFS file name used by the reader, if cached in FME Objects, which stores the cached version of the features for this feature type. Note that a single FFS file may contain multiple feature types. This attribute should not be set if there is no cache, which may occur if the reader is spatially enabled or supports the metadata constraint and all requested subconstraints. If one wants only a subset of metadata attributes returned and this attribute is part of that subset, then fme_cache_file_name should be on the query feature. Currently implemented by the Universal Reader only and does not make sense for other native readers and should not be set by an IFMEReader. - If one wants only a subset of metadata attributes returned and the extents are part of that subset, then fme_extents should be on the query feature. Specifying fme_extents on the query feature will result in the returned metadata feature containing the extents as the feature's geometry, in addition to the extents being set using the min and max attributes. - If one wants only a subset of metadata attributes returned and some set of min/max x,y,z are part of that subset, then the appropriate min/max attributes should be on the query feature. Specifying min/max attributes on the query feature will mean only the requested min/max attributes will be returned on the metadata feature; the metadata feature will not have any geometry on it as it would if the attribute fme_extents was present on the query feature. fme_get_version_list The fme_get_version_list is used to received a list of all possible versions that the current user can access. Additional information may be provided about the version including when it was created, a description of the version, and the name of its parent version. This search type is only applicable to databases supporting versioning (e.g. ArcSDE). The constraint feature and returned version info feature are described below. Unlike other search types, the fme_get_version_list search type does not support any primitives. Each feature returned will represent a single version. The following would be an example of a constraint feature: Intent: fme_search_type = fme_get_version_list (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); fmeFeature->setAttribute("fme_search_type", "fme_get_version_list"); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_search_type' has value `fme_metadata' Geometry Type: Unknown (0) ===================================================================== Metadata feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `VersionInfo' Attribute(string): `fme_type' has value `fme_no_geom' Attribute(string): `fme_version_access' has value `public' Attribute(string): `fme_version_creation_time' has value `20041019091455' Attribute(string): `fme_version_description' has value `child of SDE.DEFAULT' Attribute(string): `fme_version_name' has value `DEV.left-branch' Attribute(string): `fme_version_parent_name' has value `SDE.DEFAULT' Geometry Type: Unknown (0) =========================================================================== The feature type of the returned version feature is always VersionInfo. fme_get_historical_version_list The fme_get_historical_version_list is used to retrieve a list of all possible historical markers (versions) that the current user can access. Additional information may be provided about the version including its name and the timestamp it was created with. This search type is only applicable to databases supporting historical versioning (e.g. ArcSDE Geodatabase). The constraint feature and returned version info feature are described below. Unlike other search types, the fme_get_historical_version_list search type does not support any primitives. Each feature returned will represent a single version. The following would be an example of a constraint feature: Intent: fme_search_type = fme_get_historical_version_list (required) Code: fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); fmeFeature->setAttribute("fme_search_type", "fme_get_historical_version_list"); fmeReader->setConstraints(*fmeFeature); Constraint Feature: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `MY_CONSTRAINT_FEATURE' Attribute(string): `fme_search_type' has value `fme_get_historical_version_list' Geometry Type: Unknown (0) =========================================================================== Metadata feature returned: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Feature Type: `VersionInfo' Attribute(string): `fme_type' has value `fme_no_geom' Attribute(string): `fme_version_name' has value `New Marker' Attribute(string): `fme_historical_version_timestamp' has value `1/1/2006 12:00:01 AM' Geometry Type: Unknown (0) =========================================================================== The feature type of the returned version feature is always VersionInfo. fme_spatial_interaction (DRAFT - This is search type is still being developed) The fme_spatial_interaction search type supports the fme_interaction, fme_where, fme_type{} and fme_feature_type{} primitives. With this search type, the geometry of the constraint feature is used as the search feature. The search feature is used along with the specified spatial interaction to query the database. All features which satisfy the are spatial interaction are returned. Given the argument "fme_interaction", getProperties() must return a list of spatial interactions supported by the format. This list can include OGC defined interactions, format specific spatial interactions, DE-9IM strings, or "DE9IM:ALL" to indicate that the format supports arbitrary DE-9IM strings. In order to differentiate between format specific interactions and OGC defined interactions, any format specific interactions must be prefixed with a format identifier (e.g. the short format name) and a colon. - Unless clearly indicated by the name, interactions are expected to be applied "query geom <interaction> table geom", e.g. query geom CONTAINS table geom Readers that support reading from multiple geometry sources (eg columns) should apply spatial interactions in an OR fashion: A feature satisfies an interaction if any component geometry satisfies the interaction, and all geometry will be returned if any component satisfies the interaction. Code: FME_Boolean getProperties(const char* propertyCategory , IFMEStringArray &values) { FME_Boolean allProps = FME_FALSE; ObsoleteString category = propertyCategory; if(category == kFME_ReaderPropAll) //"*" { allProps = FME_TRUE; } values.clear(); if(category == "fme_spatial_interaction" || allProps ) { values.append( "fme_spatial_interaction" ); values.append( "fme_interaction" ); //Allow spatial interaction queries. } else if(category == "fme_interaction" || allProps ) { values.append("fme_interaction"); values.append("CONTAINS"); //Allow OGC named predicates. values.append("fme_interaction"); values.append("ORACLE:CONTAINS"); //Allow format specific named predicates. values.append("fme_interaction"); values.append("TT*F*F**T"); //Allow specific DE-9IM strings. values.append("fme_interaction"); values.append("DE9IM:ALL"); //Allow arbitrary DE-9IM strings. } if(values.entries() > 0) { return FME_TRUE; } return FME_FALSE; } Possible fme_interaction Values OGC defined interactions EQUALS, DISJOINT, TOUCHES, CROSSES, WITHIN, OVERLAPS, CONTAINS, INTERSECTS These eight spatial relationships are defined in OGC 06-103r3 and do not require any prefix. The spatial interactions are the same as the predicates used in the SpatialFilterFactory and SpatialRelationshipFactory. Only formats that are OGC compliant should use these predicates, otherwise they should use the format specific relationship. Format specific interactions ORACLE:COVEREDBY, MYSQL:INTERSECTS Formats that support interactions outside of those define by the OGC, or formats that are not OGC compliant should indicate this with a prefix consisting of an identifier and a colon. DE-9IM strings T*FFF*TTT DE-9IM strings must be of the form (T|F|0|1|2|\*){9}. Code: IFMEStringArray *fmeFeatureTypes = fmeSession->createStringArray(); fmeFeatureTypes->append("fun_shapes"); fmeFeatureTypes->append("boring_shapes"); IFMEStringArray *fmeTypes = fmeSession->createStringArray(); fmeTypes->append("fme_line"); fmeTypes->append("fme_polygon"); IFMEStringArray *spatialInteractions = fmeSession->createStringArray(); spatialInteractions ->append("ORACLE:ANYINTERACT"); spatialInteractions ->append("ORACLE:COVERS"); fmeFeature->resetFeature(); fmeFeature->setFeatureType("MY_CONSTRAINT_FEATURE"); fmeFeature->setAttribute("fme_search_type", "fme_spatial_interaction"); //Required constraint type. fmeFeature->setListAttribute("fme_interaction", *spatialInteractions); //Required interactions list. fmeFeature->setAttribute("fme_where", "Colour = 'Blue'"); //Optional WHERE clause fmeFeature->setListAttribute("fme_feature_type", *fmeFeatureTypes); //Recommended feature types list. fmeFeautre->setListAttribute("fme_type", *fmeTypes); //Optional FME types list. fmeReader->setConstraints(*fmeFeature); Notable setConstraints Clients (DRAFT) Authors of readers should use this as a guide to determine which constraints are most interesting to implement. Constraints that are implemented by UniversalReader are not listed here. Reader Settings Box Envelope Passes envelope parameters to reader only when getProperties advertises support for fme_envelope_intersects. Transformers FeatureReader Will use the most appropriate search type given the filtering that was requested. Filtering not natively supported will be emulated in the most efficient way possible (note that fme_where cannot be emulated). fme_envelope_intersects fme_feature_type fme_where fme_all_features fme_feature_type fme_where fme_spatial_interaction (pending PR#67524) fme_feature_type fme_interaction fme_where Joiner fme_db_join SqlCreator/Executor fme_execute_sql fme_schema_from_query ArcGIS Data Interoperability note: Data Interoperability Extension (and FME Extension) for ArcGIS Desktop are not being actively updated. Also, the new ArcGIS Pro does not use setConstraints. As such, new formats won't need to satisfy these setConstraints calls. fme_metadata fme_feature_type fme_feature_identifier fme_geometry fme_all_features fme_feature_type fme_where (PR#58633 proposes preferring fme_db_join) fme_envelope_intersects fme_feature_type FME Data Inspector (see internal "FME Data Inspector - Development Notes") fme_metadata fme_feature_type fme_extents fme_all_features fme_feature_type fme_envelope_intersects fme_feature_type fme_envelope_width_in_pixels fme_envelope_height_in_pixels