Changes between Version 29 and Version 30 of FDORfc50


Ignore:
Timestamp:
Jun 23, 2010, 8:58:53 AM (14 years ago)
Author:
romicadascalescu
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • FDORfc50

    v29 v30  
    3535We have a few options from which we can chose in order to achieve our goal:
    3636
    37     * Add a new select command e.g. FdoIJoinSelect derived from FdoISelect, add a new command type and caller needs to ensure that command exist in the provider command capabilities before calling this interface. A small improvement here we can add two classes FdoIJoinSelect (the interface having only pure methods) and !FdoJoinSelect (having a default implementation of those methods). All providers can use the class with a base implementation and in the future in case we want to add a new method we just add a default implementation in !FdoJoinSelect, however this adds more complexity to the API since developer would be confused which class should use as base class in his implementation.
     37    * Add a new select command e.g. FdoIJoinSelect derived from FdoISelect, add a new command type and caller needs to ensure that command exist in the provider command capabilities before calling this interface. A small improvement here we can add two classes FdoIJoinSelect (the interface having only pure methods) and !FdoJoinSelect (having a default implementation of the new method). All providers can use the class with a base implementation and in the future in case we want to add a new method we just add a default implementation in !FdoJoinSelect, however this adds more complexity to the API since developer would be confused which class should use as base class in his implementation.
    3838        * '''Pros''': will not change the FdoISelect command, all other providers do not have to change anything on their side, and only in case a provider wants to support this command it has to implement it and expose it as supported.[[BR]]
    3939        * '''Cons''': We add a new command and a new type command, we already have a FdoIExtendedSelect for scrollable readers and users can be confused by those two commands. This will add more complexity in the API.
    4040
    41     * Enhance FdoISelect, add two new methods ''!GetFeatureClassNames()'' and ''!GetJoinCriteria()''. Create an !FdoSelect base class and add default implementers for these methods. Then each provider would be changed to base their select command implementations on !FdoSelect instead of FdoISelect. To allow the join functionality to be fully integrated, two new capability functions will be added to the FDO FdoIConnectionCapabilities Interface so that applications can determine if a provider supports the join criteria and supported join types. These new capabilities would be named: !SupportsJoins() & !GetJoinTypes(). Again, if future enhancements are ever made to FdoISelect, the need to change each provider would be eliminated.
     41    * Enhance FdoISelect, add a new method ''!GetJoinCriteria()''. Create an !FdoSelect base class and add default implementer for this method. Then each provider would be changed to base their select command implementations on !FdoSelect instead of FdoISelect. To allow the join functionality to be fully integrated, two new capability functions will be added to the FDO FdoIConnectionCapabilities Interface so that applications can determine if a provider supports the join criteria and supported join types. These new capabilities would be named: !SupportsJoins() & !GetJoinTypes(). Again, if future enhancements are ever made to FdoISelect, the need to change each provider would be eliminated.
    4242          * '''Pros''': this solution will not add more complexity to the API.[[BR]]
    4343          * '''Cons''': We need to change all the providers leading to a big effort from everyone.
    4444
    45      * Enhance FdoISelect, add two new methods ''!GetFeatureClassNames()'' and ''!GetJoinCriteria()'' with the default implementation of these methods throwing an exception. Providers which want to implement these new methods must override them and provide a detailed implementation. Even though FdoISelect is declared as ''interface'' we do not have real interfaces in the FDO C++ API, and abstract methods can co-exist with those that have a default implementation. A good example here are the locking methods on the select command. Most  providers do not support locking and have to provide an empty implementation (usually to throw an exception), creating more code on provider side. A better plan would have provided a default implementation in the FdoISelect base class. Following this idea, this alternative will just modify the FdoISelect base class, allowing providers that that will not support joins to remain unchanged. These providers will inherit the default implementation. Looking at FdoISelect there are already two methods which provide default implementation: !AddRef() and Release(), so adding default implementation for the new methods will not be something totally new. As with option 2 above: Two new capability functions will be added to the FDO FdoIConnectionCapabilities Interface so that applications can determine if a provider supports the join criteria and supported join types. These new capabilities would be named: !SupportsJoins() & !GetJoinTypes().
     45     * Enhance FdoISelect, add a new method ''!GetJoinCriteria()'' with the default implementation of the method throwing an exception. Providers which want to implement this new method must override it and provide a detailed implementation. Even though FdoISelect is declared as ''interface'' we do not have real interfaces in the FDO C++ API, and abstract methods can co-exist with those that have a default implementation. A good example here are the locking methods on the select command. Most  providers do not support locking and have to provide an empty implementation (usually to throw an exception), creating more code on provider side. A better plan would have provided a default implementation in the FdoISelect base class. Following this idea, this alternative will just modify the FdoISelect base class, allowing providers that that will not support joins to remain unchanged. These providers will inherit the default implementation. Looking at FdoISelect there are already two methods which provide default implementation: !AddRef() and Release(), so adding default implementation for the new method will not be something totally new. As with option 2 above: Two new capability functions will be added to the FDO FdoIConnectionCapabilities Interface so that applications can determine if a provider supports the join criteria and supported join types. These new capabilities would be named: !SupportsJoins() & !GetJoinTypes(). A few other cnahes must be done in order to handle sub-selects.
    4646         * '''Pros''': this solution will not add more complexity to the API, we do not need to change any provider.[[BR]]
    4747         * '''Cons''': None.
     
    4949== Proposed Solution ==
    5050
    51 The last option seems to be the best solution since will not enforce other providers to add a blank implementation for those new methods and also will not add a new command. We avoid having two select commands one "extended" and one "join" this way we also eliminate a confusion which might show-up in commands naming. Also it opens a different approach to update a base class without changing all providers to add a blank implementation.
    52 
    53 The new methods added on FdoISelect will have a default implementation throwing an exception:
     51The last option seems to be the best solution since will not enforce other providers to add a blank implementation for the new method and also will not add a new command. We avoid having two select commands one "extended" and one "join" this way we also eliminate a confusion which might show-up in commands naming. Also it opens a different approach to update a base class without changing all providers to add a blank implementation.
     52
     53The new method added on FdoISelect will have a default implementation throwing an exception:
    5454
    5555{{{
    5656  class FdoISelect : public FdoIBaseSelect
    5757  {
    58      /// new added methods
    59 
    60      /// \brief
    61      /// Gets the feature class names collection.
    62      ///
    63      /// \return
    64      /// Returns the collection.
    65      ///
    66      FDO_API virtual FdoIdentifierCollection* GetFeatureClassNames()
    67      {
    68           throw FdoException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_3_NOTIMPLEMENTED)));
    69      }
     58     /// new added method
    7059
    7160     /// \brief
     
    8271}}}
    8372
    84 === Selecting from Multiple Classes ===
    85 
    86 We should be able to select from multiple classes and have filters applied on any class attributes. In order to be able to achieve that objective, we can use FdoISelect::!GetFeatureClassNames() and add all classes we want to select from. The filter must be based on properties from the selected classes and filter can be validated at run time when the whole select is built. In this collection we can have:
    87     * !FdoIdentifier’s in case we just need to pass a class name.
    88     * !FdoComputedIdentifier’s having a name and as expression value an !FdoIdentifier, this way we can get aliases, e.g. !ClassName AS !NewClassName. We already use computed identifiers in our API for expressions and we provide a name and an expression value. In this case it will be the same, since an alias is actually an expression: we provide an alias (name) and the real name of the class.
    89     * !FdoClassComputedIdentifier’s which is a FdoISelect having a name. This option might not be supported by all RDBMS providers and it depends of the internal implementation. This class behaves like a computed class which will be evaluated at run time and really depends of the provider implementation. This new class will help to define sub-selects. Refer to '''Handle Sub-Selects''' below.
    90 
    91 The following sections will use some SQL examples just to illustrate things we are trying to achieve, each RBDMS-based provider will translate FDO selects in server side SQL depending of the server capabilities.
    92 
    93     ''SELECT * FROM class1 AS p1, class2 AS p2 WHERE p1.ID=p2.!FeatId AND SPATIAL_COND(p1.GEOM, GEOM_VAL);''
    94 
    95 Below we added some C++ code on how caller can use this new improvement to achieve above select statement:
    96 
    97 {{{
    98       FdoPtr<FdoISelect> sel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select));
    99       FdoPtr<FdoIdentifierCollection> fclasscoll = = sel->GetFeatureClassNames();
    100 
    101       FdoPtr<FdoIdentifier> fcname1 = FdoIdentifier::Create(L"class1");
    102       FdoPtr<FdoComputedIdentifier> fcp1 = FdoComputedIdentifier::Create(L"p1", fcname1);
    103       fclasscoll->Add(fcp1);
    104 
    105       FdoPtr<FdoIdentifier> fcname2 = FdoIdentifier::Create(L"class2");
    106       FdoPtr<FdoComputedIdentifier> fcp2 = FdoComputedIdentifier::Create(L"p2", fcname2);
    107       fclasscoll->Add(fcp2);
    108 
    109       FdoPtr<FdoFilter> filter = FdoFilter::Parse(L"p1.ID=p2.FeatId AND Geometry INTERSECTS GeomFromText('CURVESTRING(...)')");
    110       sel->SetFilter(filter);
    111 
    112       FdoPtr<FdoIFeatureReader> rdr = sel->Execute();
    113 }}}
    114 
    115 ''NOTE:'' In the base class we have a method named !GetFeatureClassName, in case caller will use it and the !FdoIdentifier is not added into !GetFeatureClassNames we can add it at Execute time.
    116 
    11773=== Handling Joins ===
    11874
     
    12278      class FdoJoinCriteria : public FdoIDisposable
    12379      {
     80      protected:
     81          /// Constructs a default instance of a parameter.
     82          FdoJoinCriteria();
     83
     84          /// Constructs an instance of a parameter using the specified arguments.
     85          FdoJoinCriteria(FdoIdentifier* joinClass, FdoJoinType joinType);
     86
     87          /// Constructs an instance of a parameter using the specified arguments.
     88          FdoJoinCriteria(FdoIdentifier* joinClass, FdoJoinType joinType, FdoFilter* filter);
     89         
     90          /// Constructs an instance of a parameter using the specified arguments.
     91          FdoJoinCriteria(FdoString* name, FdoIdentifier* joinClass, FdoJoinType joinType);
     92
     93          /// Constructs an instance of a parameter using the specified arguments.
     94          FdoJoinCriteria(FdoString* name, FdoIdentifier* joinClass, FdoJoinType joinType, FdoFilter* filter);
    12495      public:
    12596          /// Constructs a default instance of a join criteria.
    12697          FDO_API static FdoJoinCriteria* Create();
     98
     99          /// Constructs a full defined instance of a join criteria.
     100          /// In this case Name = joinClass->GetName().
     101          FDO_API static FdoJoinCriteria* Create(FdoIdentifier* joinClass,
     102                                                 FdoJoinType joinType);
     103
     104          /// Constructs a full defined instance of a join criteria.
     105          /// In this case Name = joinClass->GetName().
     106          FDO_API static FdoJoinCriteria* Create(FdoIdentifier* joinClass,
     107                                                 FdoJoinType joinType,
     108                                                 FdoFilter* filter);
     109
     110          /// Constructs a full defined instance of a join criteria.
     111          FDO_API static FdoJoinCriteria* Create(FdoString* name,
     112                                                 FdoIdentifier* joinClass,
     113                                                 FdoJoinType joinType);
    127114
    128115          /// Constructs a full defined instance of a join criteria.
     
    175162}}}
    176163
    177 We need to add two new methods in connection capabilities: supports join selects (to avoid an exception when a user will try to use these two new methods from FdoISelect) and also supported join types which can be a collection or a value as OR between values, since all join types cannot be more than we can fit in a int32 using OR e.g.: val1|val2.
     164We need to add two new methods in connection capabilities: supports join selects (to avoid an exception when a user will try to use the new method from FdoISelect) and also supported join types which can be a collection or a value as OR between values, since all join types cannot be more than we can fit in a int32 using OR e.g.: val1|val2.
    178165
    179166{{{
     
    217204{{{
    218205      FdoPtr<FdoISelect> sel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select));
    219       FdoPtr<FdoIdentifierCollection> fclasscoll = = sel->GetFeatureClassNames();
     206
     207      FdoPtr<FdoIdentifier> fcpoint = FdoIdentifier::Create(L"p");
     208      /// In case we need an alias we can do:
     209      /// FdoPtr<FdoComputedIdentifier> pAlias = FdoComputedIdentifier::Create(L"pAlias", fcpoint);
     210      sel->SetFeatureClassName(fcpoint); // set the main class
     211
    220212      FdoPtr<FdoJoinCriteriaCollection> jcrit = sel->GetJoinCriteria();
    221 
    222       FdoPtr<FdoIdentifier> fcpoint = FdoIdentifier::Create(L"p");
    223       fclasscoll->Add(fcpoint);
    224213
    225214      FdoPtr<FdoIdentifier> jcCls1 = FdoIdentifier::Create(L"pxy");
     
    239228
    240229
     230=== Selecting from Multiple Classes ===
     231
     232We should be able to select from multiple classes and have filters applied on any class attributes. In order to be able to achieve that objective, we can use FdoISelect::!GetJoinCriteria() and add all classes we want to select from. The filter must be based on properties from the selected classes and filter can be validated at run time when the whole select is built. In this collection we can have:
     233    * !FdoIdentifier’s in case we just need to pass a class name.
     234    * !FdoComputedIdentifier’s having a name and as expression value an !FdoIdentifier, this way we can get aliases, e.g. !ClassName AS !NewClassName. We already use computed identifiers in our API for expressions and we provide a name and an expression value. In this case it will be the same, since an alias is actually an expression: we provide an alias (name) and the real name of the class.
     235
     236The following sections will use some SQL examples just to illustrate things we are trying to achieve, each RBDMS-based provider will translate FDO selects in server side SQL depending of the server capabilities.
     237
     238    ''SELECT * FROM class1 AS p1, class2 AS p2 WHERE p1.ID=p2.!FeatId AND SPATIAL_COND(p1.GEOM, GEOM_VAL);''
     239
     240Below we added some C++ code on how caller can use this new improvement to achieve above select statement:
     241
     242{{{
     243      FdoPtr<FdoISelect> sel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select));
     244
     245      FdoPtr<FdoIdentifier> fcname1 = FdoIdentifier::Create(L"class1");
     246      // we need this only in case we want to create an alias for the class, otherwise we can pass fcname1
     247      FdoPtr<FdoComputedIdentifier> fcp1 = FdoComputedIdentifier::Create(L"p1", fcname1);
     248      sel->SetFeatureClassName(fcpoint); // set the main class
     249
     250      FdoPtr<FdoJoinCriteriaCollection> jcrit = sel->GetJoinCriteria();
     251
     252      FdoPtr<FdoIdentifier> fcname2 = FdoIdentifier::Create(L"class2");
     253      FdoPtr<FdoJoinCriteria> jc1 = FdoJoinCriteria::Create(L"p2", fcname2, FdoJoinType_None);
     254      jcrits->Add(jc1);
     255
     256      FdoPtr<FdoFilter> filter = FdoFilter::Parse(L"p1.ID=p2.FeatId AND Geometry INTERSECTS GeomFromText('CURVESTRING(...)')");
     257      sel->SetFilter(filter);
     258
     259      FdoPtr<FdoIFeatureReader> rdr = sel->Execute();
     260}}}
     261
     262
    241263=== Handle Sub-Selects ===
    242264
     
    244266
    245267{{{
    246       class FdoComputedClassIdentifier : public FdoIdentifier
    247       {
    248       public:
    249           /// Constructs a default instance of a computed class identifier.
    250           FDO_API static FdoComputedClassIdentifier* Create();
    251 
    252           /// Constructs an instance of a computed class identifier
    253           /// using the specified arguments.
    254           FDO_API static FdoComputedClassIdentifier* Create(
    255                                          FdoString* name,
    256                                          FdoISelect* select);
    257 
    258           /// Gets the sub-select of the computed class identifier.
    259           FDO_API FdoISelect* GetSelect();
    260 
    261           /// Sets the sub-select of the computed class identifier.
    262           FDO_API void SetSelect(FdoISelect* value);
    263 
    264           /// Returns the type of the expression used to identify the
    265           /// type and avoid dynamic casts
    266           FDO_API FdoItemExpressionType GetExpressionType()
    267           {
    268               return FdoItemExpressionType_ComputedClassIdentifier;
    269           }
    270       };
     268/// \brief
     269/// The FdoSubSelectExpression class derives from FdoExpression and can be used with IN condition
     270/// to test if a property is in a range of values returned by this sub-select
     271class FdoSubSelectExpression : public FdoExpression
     272{
     273/// \cond DOXYGEN-IGNORE
     274protected:
     275    /// Constructs a default instance of an FdoSubSelectExpression.
     276    FdoSubSelectExpression();
     277
     278    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     279    FdoSubSelectExpression(FdoIdentifier* className, FdoIdentifier* propertyName);
     280
     281    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     282    FdoSubSelectExpression(FdoIdentifier* className, FdoIdentifier* propertyName, FdoFilter* filter);
     283   
     284    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     285    FdoSubSelectExpression(FdoIdentifier* className, FdoIdentifier* propertyName, FdoJoinCriteriaCollection* joinCritColl);
     286   
     287    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     288    FdoSubSelectExpression(FdoIdentifier* className, FdoIdentifier* propertyName, FdoFilter* filter, FdoJoinCriteriaCollection* joinCritColl);
     289
     290    virtual ~FdoSubSelectExpression();
     291
     292    virtual void Dispose();
     293/// \endcond
     294
     295public:
     296    /// \brief
     297    /// Constructs a default instance of an FdoSubSelectExpression.
     298    ///
     299    /// \return
     300    /// Returns FdoSubSelectExpression
     301    ///
     302    FDO_API static FdoSubSelectExpression* Create();
     303
     304    /// \brief
     305    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     306    ///
     307    /// \param className
     308    /// Input class name
     309    /// \param propertyName
     310    /// Input property name
     311    ///
     312    /// \return
     313    /// Returns FdoSubSelectExpression
     314    ///
     315    FDO_API static FdoSubSelectExpression* Create(FdoIdentifier* className, FdoIdentifier* propertyName);
     316
     317    /// \brief
     318    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     319    ///
     320    /// \param className
     321    /// Input class name
     322    /// \param propertyName
     323    /// Input property name
     324    /// \param filter
     325    /// Input main filter
     326    ///
     327    /// \return
     328    /// Returns FdoSubSelectExpression
     329    ///
     330    FDO_API static FdoSubSelectExpression* Create(FdoIdentifier* className, FdoIdentifier* propertyName, FdoFilter* filter);
     331
     332    /// \brief
     333    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     334    ///
     335    /// \param className
     336    /// Input class name
     337    /// \param propertyName
     338    /// Input property name
     339    /// \param joinCritColl
     340    /// Input join Criteria collection
     341    ///
     342    /// \return
     343    /// Returns FdoSubSelectExpression
     344    ///
     345    FDO_API static FdoSubSelectExpression* Create(FdoIdentifier* className, FdoIdentifier* propertyName, FdoJoinCriteriaCollection* joinCritColl);
     346
     347    /// \brief
     348    /// Constructs an instance of an FdoSubSelectExpression using the specified arguments.
     349    ///
     350    /// \param className
     351    /// Input class name
     352    /// \param propertyName
     353    /// Input property name
     354    /// \param filter
     355    /// Input main filter
     356    /// \param joinCritColl
     357    /// Input join Criteria collection
     358    ///
     359    /// \return
     360    /// Returns FdoSubSelectExpression
     361    ///
     362    FDO_API static FdoSubSelectExpression* Create(FdoIdentifier* className, FdoIdentifier* propertyName, FdoFilter* filter, FdoJoinCriteriaCollection* joinCritColl);
     363
     364    /// \brief
     365    /// Gets the name of the join class.
     366    ///
     367    /// \return
     368    /// Returns the name of the join class
     369    ///
     370    FDO_API FdoIdentifier* GetClassName();
     371
     372    /// \brief
     373    /// Sets the name of the join class.
     374    /// It can be a computed identifier (only an alias)
     375    ///
     376    /// \param value
     377    /// Input the name of the join class
     378    ///
     379    /// \return
     380    /// Returns nothing
     381    ///
     382    FDO_API void SetClassName(FdoIdentifier* value);
     383
     384    /// \brief
     385    /// Gets the name of the property.
     386    ///
     387    /// \return
     388    /// Returns the name of the property
     389    ///
     390    FDO_API FdoIdentifier* GetPropertyName();
     391
     392    /// \brief
     393    /// Sets the name of the property.
     394    /// It can be a computed identifier (alias or expression)
     395    ///
     396    /// \param value
     397    /// Input the name of the property
     398    ///
     399    /// \return
     400    /// Returns nothing
     401    ///
     402    FDO_API void SetPropertyName(FdoIdentifier* value);
     403
     404    /// \brief
     405    /// Gets join criteria collection.
     406    ///
     407    /// \return
     408    /// Returns FdoJoinCriteriaCollection
     409    ///
     410    FDO_API FdoJoinCriteriaCollection* GetJoinCriteria();
     411
     412    /// \brief
     413    /// Sets the join criteria collection.
     414    ///
     415    /// \param value
     416    /// Input FdoJoinCriteriaCollection.
     417    ///
     418    /// \return
     419    /// Returns nothing
     420    ///
     421    FDO_API void SetJoinCriteria(FdoJoinCriteriaCollection* value);
     422
     423    /// \brief
     424    /// Gets the join filter.
     425    ///
     426    /// \return
     427    /// Returns FdoFilter
     428    ///
     429    FDO_API FdoFilter* GetFilter();
     430
     431    /// \brief
     432    /// Sets the join filter.
     433    ///
     434    /// \param value
     435    /// Input FdoFilter.
     436    ///
     437    /// \return
     438    /// Returns nothing
     439    ///
     440    FDO_API void SetFilter(FdoFilter* value);
     441
     442    /// \brief
     443    /// Overrides FdoFilter.Process to pass the FdoSubSelectExpression to the appropriate
     444    /// filter processor operation.
     445    ///
     446    /// \param p
     447    /// Input filter processor
     448    ///
     449    /// \return
     450    /// Returns nothing
     451    ///
     452    FDO_API void Process(FdoIExpressionProcessor* p);
     453   
     454    /// \brief
     455    /// Returns the well defined text representation of this expression.
     456    ///
     457    /// \return
     458    /// Returns the well defined text string
     459    ///
     460    FDO_API FdoString* ToString();
     461
     462    /// \brief
     463    /// Gets Item Expression Type.
     464    ///
     465    /// \return
     466    /// Returns FdoItemExpressionType (FdoItemExpressionType_SubSelectExpression)
     467    ///
     468    FDO_API FdoItemExpressionType GetExpressionType();
     469
     470    /// \brief
     471    /// Converts the filter expression to its well defined text representation.
     472    ///
     473    /// \return
     474    /// Returns well defined text string
     475    ///
     476    FdoString* ToStringInternal( FdoIdentifierCollection *pIdCol );
     477
     478private:
     479    FdoIdentifier* m_className;
     480    FdoIdentifier* m_propertyName;
     481    FdoFilter* m_filter;
     482    FdoJoinCriteriaCollection* m_joinCritColl;
     483};
     484}}}
     485
     486FDO parser will be modified and we will add new keywords: SELECT, JOIN, JOINNONE, JOININNER, JOINRIGHTOUTER, JOINLEFTOUTER, JOINFULLOUTER, JOINCROSS, used to generate well defined text representation of this expression. Below there is a small example on how well defined text representation of this expression will look. SELECT, JOIN will play the same role as IN, the role of an operator and not the role of a function. JOINNONE, JOININNER, JOINRIGHTOUTER, JOINLEFTOUTER, JOINFULLOUTER, JOINCROSS will be type of join and at parse time will be converted to FdoJoinType.
     487
     488{{{
     489
     490FdoPtr<FdoFilter> flt = FdoFilter::Parse(L"FeatId IN ( SELECT (CLS, (PROP*30) AS P1, P1 >= 45, JOIN(CLS2 AS CC, JOININNER, CLS.P1=CC.P2), JOIN(CLS2 AS CC2, JOINRIGHTOUTER, CLS.P1=CC2.P2)) )");
     491FdoString* str = flt->ToString();
     492printf ("%ls\n", str);
     493 // we get on the screen
     494 //
     495 //     FeatId IN (SELECT(CLS,( PROP*30 ) AS P1,P1 >= 45,JOIN(( CLS2 ) AS CC,JOININNER,CLS.P1 = CC.P2),JOIN(( CLS2 ) AS CC2,JOINRIGHTOUTER,CLS.P1 = CC2.P2)))
     496
    271497}}}
    272498
     
    275501    ''SELECT * FROM point WHERE  !FeatId IN (SELECT pt.!FeatId FROM pt WHERE pt.!FeatId >= 2 AND SPATIAL_COND(pt.GEOM, GEOM_VAL));''
    276502
    277 In above case we will have two selects having following filters:
    278     Main-Select: ''!FeatId IN(:SUBSEL)''[[BR]]
    279     Sub-Select : ''pt.!FeatId >= 2 AND SPATIAL_COND(pt.GEOM, GEOM_VAL)''
    280 
    281503Below we added some C++ code on how caller can use this new improvement to achieve above select statement:
    282504
    283505{{{
    284506      FdoPtr<FdoISelect> sel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select));
    285       FdoPtr<FdoIdentifierCollection> fclasscoll = = sel->GetFeatureClassNames();
    286507
    287508      FdoPtr<FdoIdentifier> fcpoint = FdoIdentifier::Create(L"point");
    288       fclasscoll->Add(fcpoint);
    289 
    290       FdoPtr<FdoISelect> subsel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select));
    291       FdoPtr<FdoIdentifierCollection> ssfclasscoll = = subsel->GetFeatureClassNames();
    292       FdoPtr<FdoIdentifier> fcpt = FdoIdentifier::Create(L"pt");
    293       ssfclasscoll->Add(fcpt);
    294       FdoPtr<FdoFilter> ssfilter = FdoFilter::Parse(L"pt.FeatId>=2 AND Geometry INTERSECTS GeomFromText('CURVESTRING(...)')");
    295       subsel->SetFilter(ssfilter);
    296 
    297       FdoPtr<FdoComputedClassIdentifier> fcSubSel = FdoComputedClassIdentifier::Create(L"SUBSEL1", subsel);
    298       fclasscoll->Add(fcSubSel);
    299 
    300       FdoPtr<FdoFilter> filter = FdoFilter::Parse(L"FeatId IN (:SUBSEL1)");
     509      sel->SetFeatureClassName(fcpoint); // set the main class
     510
     511      FdoPtr<FdoFilter> filter= FdoFilter::Parse(L"FeatId IN(SELECT(pt, pt.FeatId, pt.FeatId>=2 AND Geometry INTERSECTS GeomFromText('CURVESTRING(...)')))");
    301512      sel->SetFilter(filter);
    302513
     
    304515}}}
    305516
    306 In order to be able to support sub-selects for ''IN'' operator we need provide a way to pass it through FDO Filter and make the parser to recognize the filter, since FDO Filter parser don’t know SQL syntax. The best way to achieve that is to pass a parameter in the filter.
    307 
    308     e.g.: ''!FeatId IN (:PARAM)''.
    309 
    310 The '':PARAM'' parameter will be replaced at execution time with the sub-select statement. In this way we allow the FDO IN() operator to handle sub-selects.
     517In order to be able to support sub-selects for ''IN'' operator we need add an additional constructor and two new methods (get/set)to FdoInCondition.
     518{{{
     519 /// This way we allow the FDO IN() operator to handle sub-selects.
     520class FdoInCondition : public FdoSearchCondition
     521{
     522/// new additions to this class
     523protected:
     524    FdoInCondition(FdoIdentifier* propertyName, FdoSubSelectExpression* subSel);
     525public:
     526    /// \brief
     527    /// Constructs an instance of an FdoInCondition using the specified arguments.
     528    ///
     529    /// \param propertyName
     530    /// Input property name
     531    /// \param subSel
     532    /// Input sub-select
     533    ///
     534    /// \return
     535    /// Returns FdoInCondition
     536    ///
     537    FDO_API static FdoInCondition* Create(FdoIdentifier* propertyName, FdoSubSelectExpression* subSel);
     538
     539    /// \brief
     540    ///  Gets the sub-select expression.
     541    ///
     542    /// \return
     543    /// Returns FdoSubSelectExpression
     544    ///
     545    FDO_API FdoSubSelectExpression* GetSubSelect();
     546
     547    /// \brief
     548    ///  Sets the sub-select expression.
     549    ///
     550    /// \return
     551    /// Returns FdoSubSelectExpression
     552    ///
     553    FDO_API void SetSubSelect(FdoSubSelectExpression* value);
     554};
     555}}}
    311556
    312557As new additions, the FDO API will define three new classes:
    313558    * !FdoJoinCriteria
    314559    * !FdoJoinCriteriaCollection
    315     * !FdoComputedClassIdentifier
     560    * !FdoSubSelectExpression
    316561
    317562and two enumerations
     
    319564    * !FdoJoinType
    320565
    321 The API will also be updated to include two new command capabilities in order to be able to detect if those methods are supported by the provider. Otherwise caller might get exceptions from the default implementation.
     566The API will also be updated to include two new command capabilities in order to be able to detect if the method is supported by the provider. Otherwise caller might get exceptions from the default implementation.
    322567    * !SupportsJoins
    323568    * !GetJoinTypes
     
    327572FdoISelectAggregates interface will be updated in the same manner in order to allow performing aggregates selects having sub-selects in the filter side.
    328573
    329 Update and delete commands will not be changed to allow such complex filters, however we can update those commands doing a similar RFC in the future if is needed.
     574Update and delete commands will not be changed to allow using this new expression as a value, however we can update those commands doing a similar RFC in the future if is needed.
    330575
    331576== Small improvements in FDO ==
     
    343588         /// Identifier e.g. PROP*5 AS EXP
    344589         FdoItemExpressionType_ComputedIdentifier,
    345          /// Identifier e.g. SELECT * FROM C1 AS CLS
    346          FdoItemExpressionType_ComputedClassIdentifier,
     590         /// Identifier e.g. SELECT PROP FROM CLS WHERE COND
     591         FdoItemExpressionType_SubSelectExpression,
    347592         /// Parameter e.g. :PROP
    348593         FdoItemExpressionType_Parameter,
     
    378623This change is required in order to be able to support properties names having special characters, like: myClass."My Property" > 10. This change will not involve any API change and will be done like a bug fix.
    379624
     625FDO filter parser needs to be updated also to support sub-selects in filter side e.g. "FeatId IN (SELECT(CLS,( PROP*30 ) AS P1,P1 >= 45,JOIN(( CLS2 ) AS CC,JOININNER,CLS.P1 = CC.P2),JOIN(( CLS2 ) AS CC2,JOINRIGHTOUTER,CLS.P1 = CC2.P2)))".
     626FDO expression parser needs to be updated to support sub-selects expressions in order to be used for other things like update/insert.
     627
    380628== Managed FDO API ==
    381629
     
    384632== Provider Implementation ==
    385633
    386 Initially, we need this for SQLite provider. Other provider developers can add it and use it as needed. The providers which decide to use this new select need to implement the new methods from the FdoISelect and return the right command capabilities.
     634Initially, we need this for SQLite provider. Other provider developers can add it and use it as needed. The providers which decide to use this new select, needs to implement the new method from the FdoISelect and return the right command capabilities.
    387635
    388636== Test Plan ==