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