Changes between Version 29 and Version 30 of FDORfc50
- Timestamp:
- 06/23/10 08:58:53 (14 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
FDORfc50
v29 v30 35 35 We have a few options from which we can chose in order to achieve our goal: 36 36 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 th ose 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. 38 38 * '''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]] 39 39 * '''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. 40 40 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. 42 42 * '''Pros''': this solution will not add more complexity to the API.[[BR]] 43 43 * '''Cons''': We need to change all the providers leading to a big effort from everyone. 44 44 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. 46 46 * '''Pros''': this solution will not add more complexity to the API, we do not need to change any provider.[[BR]] 47 47 * '''Cons''': None. … … 49 49 == Proposed Solution == 50 50 51 The last option seems to be the best solution since will not enforce other providers to add a blank implementation for th ose new methodsand 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 method sadded on FdoISelect will have a default implementation throwing an exception:51 The 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 53 The new method added on FdoISelect will have a default implementation throwing an exception: 54 54 55 55 {{{ 56 56 class FdoISelect : public FdoIBaseSelect 57 57 { 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 70 59 71 60 /// \brief … … 82 71 }}} 83 72 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 117 73 === Handling Joins === 118 74 … … 122 78 class FdoJoinCriteria : public FdoIDisposable 123 79 { 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); 124 95 public: 125 96 /// Constructs a default instance of a join criteria. 126 97 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); 127 114 128 115 /// Constructs a full defined instance of a join criteria. … … 175 162 }}} 176 163 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 the se two new methodsfrom 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.164 We 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. 178 165 179 166 {{{ … … 217 204 {{{ 218 205 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 220 212 FdoPtr<FdoJoinCriteriaCollection> jcrit = sel->GetJoinCriteria(); 221 222 FdoPtr<FdoIdentifier> fcpoint = FdoIdentifier::Create(L"p");223 fclasscoll->Add(fcpoint);224 213 225 214 FdoPtr<FdoIdentifier> jcCls1 = FdoIdentifier::Create(L"pxy"); … … 239 228 240 229 230 === Selecting from Multiple Classes === 231 232 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::!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 236 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. 237 238 ''SELECT * FROM class1 AS p1, class2 AS p2 WHERE p1.ID=p2.!FeatId AND SPATIAL_COND(p1.GEOM, GEOM_VAL);'' 239 240 Below 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 241 263 === Handle Sub-Selects === 242 264 … … 244 266 245 267 {{{ 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 271 class FdoSubSelectExpression : public FdoExpression 272 { 273 /// \cond DOXYGEN-IGNORE 274 protected: 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 295 public: 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 478 private: 479 FdoIdentifier* m_className; 480 FdoIdentifier* m_propertyName; 481 FdoFilter* m_filter; 482 FdoJoinCriteriaCollection* m_joinCritColl; 483 }; 484 }}} 485 486 FDO 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 490 FdoPtr<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)) )"); 491 FdoString* str = flt->ToString(); 492 printf ("%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 271 497 }}} 272 498 … … 275 501 ''SELECT * FROM point WHERE !FeatId IN (SELECT pt.!FeatId FROM pt WHERE pt.!FeatId >= 2 AND SPATIAL_COND(pt.GEOM, GEOM_VAL));'' 276 502 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 281 503 Below we added some C++ code on how caller can use this new improvement to achieve above select statement: 282 504 283 505 {{{ 284 506 FdoPtr<FdoISelect> sel = static_cast<FdoISelect*>(conn->CreateCommand(FdoCommandType_Select)); 285 FdoPtr<FdoIdentifierCollection> fclasscoll = = sel->GetFeatureClassNames();286 507 287 508 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(...)')))"); 301 512 sel->SetFilter(filter); 302 513 … … 304 515 }}} 305 516 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. 517 In 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. 520 class FdoInCondition : public FdoSearchCondition 521 { 522 /// new additions to this class 523 protected: 524 FdoInCondition(FdoIdentifier* propertyName, FdoSubSelectExpression* subSel); 525 public: 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 }}} 311 556 312 557 As new additions, the FDO API will define three new classes: 313 558 * !FdoJoinCriteria 314 559 * !FdoJoinCriteriaCollection 315 * !Fdo ComputedClassIdentifier560 * !FdoSubSelectExpression 316 561 317 562 and two enumerations … … 319 564 * !FdoJoinType 320 565 321 The API will also be updated to include two new command capabilities in order to be able to detect if th ose methods aresupported by the provider. Otherwise caller might get exceptions from the default implementation.566 The 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. 322 567 * !SupportsJoins 323 568 * !GetJoinTypes … … 327 572 FdoISelectAggregates interface will be updated in the same manner in order to allow performing aggregates selects having sub-selects in the filter side. 328 573 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.574 Update 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. 330 575 331 576 == Small improvements in FDO == … … 343 588 /// Identifier e.g. PROP*5 AS EXP 344 589 FdoItemExpressionType_ComputedIdentifier, 345 /// Identifier e.g. SELECT * FROM C1 AS CLS346 FdoItemExpressionType_ ComputedClassIdentifier,590 /// Identifier e.g. SELECT PROP FROM CLS WHERE COND 591 FdoItemExpressionType_SubSelectExpression, 347 592 /// Parameter e.g. :PROP 348 593 FdoItemExpressionType_Parameter, … … 378 623 This 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. 379 624 625 FDO 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)))". 626 FDO expression parser needs to be updated to support sub-selects expressions in order to be used for other things like update/insert. 627 380 628 == Managed FDO API == 381 629 … … 384 632 == Provider Implementation == 385 633 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 methodsfrom the FdoISelect and return the right command capabilities.634 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, needs to implement the new method from the FdoISelect and return the right command capabilities. 387 635 388 636 == Test Plan ==