[mapguide-commits] r8528 - in trunk/MgDev/Server/src: Services/Feature UnitTesting
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue Feb 3 03:41:32 PST 2015
Author: jng
Date: 2015-02-03 03:41:32 -0800 (Tue, 03 Feb 2015)
New Revision: 8528
Modified:
trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.cpp
trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.h
trunk/MgDev/Server/src/Services/Feature/SelectCommand.cpp
trunk/MgDev/Server/src/Services/Feature/SelectCommand.h
trunk/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp
trunk/MgDev/Server/src/UnitTesting/TestFeatureService.cpp
trunk/MgDev/Server/src/UnitTesting/TestFeatureService.h
Log:
#2530: Add support for limited ordering support for SDF and SHP providers via the FdoIExtendedSelect command. The "limit" is that ordering can only be applied on a single property for these providers, otherwise the standard unsupported exception is thrown back as usual.
Modified: trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.cpp 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.cpp 2015-02-03 11:41:32 UTC (rev 8528)
@@ -22,14 +22,14 @@
#include "SelectCommand.h"
#include "SelectAggregateCommand.h"
-MgFeatureServiceCommand* MgFeatureServiceCommand::CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType)
+MgFeatureServiceCommand* MgFeatureServiceCommand::CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType, MgFeatureQueryOptions* options)
{
Ptr<MgFeatureServiceCommand> command;
switch(commandType)
{
case FdoCommandType_Select:
{
- command = new MgSelectCommand(resource);
+ command = new MgSelectCommand(resource, options);
break;
}
case FdoCommandType_SelectAggregates:
Modified: trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.h
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.h 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/Services/Feature/FeatureServiceCommand.h 2015-02-03 11:41:32 UTC (rev 8528)
@@ -21,7 +21,7 @@
class MgFeatureServiceCommand : public MgDisposable
{
public:
- static MgFeatureServiceCommand* CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType);
+ static MgFeatureServiceCommand* CreateCommand(MgResourceIdentifier* resource, FdoCommandType commandType, MgFeatureQueryOptions* options);
virtual FdoIdentifierCollection* GetPropertyNames() = 0;
@@ -35,6 +35,9 @@
virtual void SetOrderingOption( FdoOrderingOption option ) = 0;
virtual FdoOrderingOption GetOrderingOption( ) = 0;
+ virtual bool IsExtended() { return false; }
+ virtual void SetExtendedOrderingOption(FdoString* orderBy, FdoOrderingOption option) { }
+
virtual FdoIdentifierCollection* GetGrouping() = 0;
virtual void SetGroupingFilter( FdoFilter* filter ) = 0;
virtual FdoFilter* GetGroupingFilter( ) = 0;
Modified: trunk/MgDev/Server/src/Services/Feature/SelectCommand.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/SelectCommand.cpp 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/Services/Feature/SelectCommand.cpp 2015-02-03 11:41:32 UTC (rev 8528)
@@ -30,7 +30,7 @@
// The maximum size of the subfilter for a selection query. Tune this value for optimal selection perfomance.
#define MG_MAX_SUBFILTER_SIZE 250
-MgSelectCommand::MgSelectCommand(MgResourceIdentifier* resource)
+MgSelectCommand::MgSelectCommand(MgResourceIdentifier* resource, MgFeatureQueryOptions* options)
{
CHECKARGUMENTNULL((MgResourceIdentifier*)resource, L"MgSelectCommand.MgSelectCommand");
@@ -44,9 +44,40 @@
{
throw new MgConnectionFailedException(L"MgSelectCommand.MgSelectCommand", __LINE__, __WFILE__, NULL, L"", NULL);
}
+
+ FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
+
+ // For SDF/SHP providers, they do not support ordering. But, they can support ordering through the FdoIExtendedSelect
+ // command, provided that only a single property is being ordered on. So if it is the case that normal ordering is
+ // not supported, we should try for extended select if the conditions are met.
+ bool bTryExtendedSelect = false;
+ if (NULL != options)
+ {
+ Ptr<MgStringCollection> orderProps = options->GetOrderingProperties();
+ if (NULL != orderProps.p)
+ {
+ FdoPtr<FdoICommandCapabilities> cmdCaps = fdoConn->GetCommandCapabilities();
+ if (!cmdCaps->SupportsSelectOrdering())
+ {
+ FdoInt32 cmdCount;
+ FdoInt32* cmds = cmdCaps->GetCommands(cmdCount);
+ for (FdoInt32 i = 0; i < cmdCount; i++)
+ {
+ if (FdoCommandType_ExtendedSelect == cmds[i] && orderProps->GetCount() == 1)
+ {
+ bTryExtendedSelect = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
// Create FdoISelect command
- FdoPtr<FdoIConnection> fdoConn = m_connection->GetConnection();
- m_command = (FdoISelect*)fdoConn->CreateCommand(FdoCommandType_Select);
+ if (bTryExtendedSelect)
+ m_command = (FdoIExtendedSelect*)fdoConn->CreateCommand(FdoCommandType_ExtendedSelect);
+ else
+ m_command = (FdoISelect*)fdoConn->CreateCommand(FdoCommandType_Select);
CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.MgSelectCommand");
}
@@ -106,6 +137,27 @@
m_command->SetOrderingOption(option);
}
+bool MgSelectCommand::IsExtended()
+{
+ CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetExtendedOrderingOption");
+ FdoIExtendedSelect* extSelect = dynamic_cast<FdoIExtendedSelect*>(m_command.p);
+ if (NULL != extSelect)
+ {
+ return true;
+ }
+ return false;
+}
+
+void MgSelectCommand::SetExtendedOrderingOption(FdoString* orderBy, FdoOrderingOption option)
+{
+ CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.SetExtendedOrderingOption");
+ FdoIExtendedSelect* extSelect = dynamic_cast<FdoIExtendedSelect*>(m_command.p);
+ if (NULL != extSelect)
+ {
+ extSelect->SetOrderingOption(orderBy, option);
+ }
+}
+
FdoOrderingOption MgSelectCommand::GetOrderingOption()
{
CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.GetOrderingOption");
@@ -165,27 +217,37 @@
{
FdoPtr<FdoIFeatureReader> reader;
- // Break up the filter into smaller chunks
- FdoPtr<MgFdoFilterCollection> subFilters = this->GetSubFilters();
-
CHECKNULL((FdoISelect*)m_command, L"MgSelectCommand.Execute");
-
- // Execute queries using the smaller filters and collect the results of the queries into a reader collection.
- FdoPtr<MgFdoReaderCollection> frc = MgFdoReaderCollection::Create();
-
- for (FdoInt32 filterIndex = 0; filterIndex < subFilters->GetCount(); filterIndex++)
+ FdoIExtendedSelect* extSelect = dynamic_cast<FdoIExtendedSelect*>(m_command.p);
+ if (NULL != extSelect)
{
- FdoPtr<FdoFilter> filter = subFilters->GetItem(filterIndex);
- m_command->SetFilter(filter);
- reader = m_command->Execute();
+ FdoPtr<FdoIScrollableFeatureReader> scReader = extSelect->ExecuteScrollable();
+ CHECKNULL((FdoIScrollableFeatureReader*)scReader, L"MgSelectCommand.Execute");
- frc->Add(reader);
+ return new MgServerFeatureReader(m_connection, scReader);
}
+ else
+ {
+ // Break up the filter into smaller chunks
+ FdoPtr<MgFdoFilterCollection> subFilters = this->GetSubFilters();
- FdoPtr<MgFdoFeatureReader> featureReader = new MgFdoFeatureReader(frc);
- CHECKNULL((FdoIFeatureReader*)featureReader, L"MgSelectCommand.Execute");
+ // Execute queries using the smaller filters and collect the results of the queries into a reader collection.
+ FdoPtr<MgFdoReaderCollection> frc = MgFdoReaderCollection::Create();
- return new MgServerFeatureReader(m_connection, featureReader);
+ for (FdoInt32 filterIndex = 0; filterIndex < subFilters->GetCount(); filterIndex++)
+ {
+ FdoPtr<FdoFilter> filter = subFilters->GetItem(filterIndex);
+ m_command->SetFilter(filter);
+ reader = m_command->Execute();
+
+ frc->Add(reader);
+ }
+
+ FdoPtr<MgFdoFeatureReader> featureReader = new MgFdoFeatureReader(frc);
+ CHECKNULL((FdoIFeatureReader*)featureReader, L"MgSelectCommand.Execute");
+
+ return new MgServerFeatureReader(m_connection, featureReader);
+ }
}
bool MgSelectCommand::IsSupportedFunction(FdoFunction* fdoFunc)
Modified: trunk/MgDev/Server/src/Services/Feature/SelectCommand.h
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/SelectCommand.h 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/Services/Feature/SelectCommand.h 2015-02-03 11:41:32 UTC (rev 8528)
@@ -27,7 +27,7 @@
DECLARE_CLASSNAME(MgServerSqlProcessor)
public:
- MgSelectCommand(MgResourceIdentifier* resource);
+ MgSelectCommand(MgResourceIdentifier* resource, MgFeatureQueryOptions* options);
virtual ~MgSelectCommand();
virtual FdoIdentifierCollection* GetPropertyNames();
@@ -42,6 +42,9 @@
virtual void SetOrderingOption( FdoOrderingOption option );
virtual FdoOrderingOption GetOrderingOption( );
+ virtual bool IsExtended();
+ virtual void SetExtendedOrderingOption(FdoString* orderBy, FdoOrderingOption option);
+
virtual FdoIdentifierCollection* GetGrouping();
virtual void SetGroupingFilter( FdoFilter* filter );
virtual FdoFilter* GetGroupingFilter( );
Modified: trunk/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp
===================================================================
--- trunk/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp 2015-02-03 11:41:32 UTC (rev 8528)
@@ -132,7 +132,7 @@
#ifdef DEBUG_FDO_JOIN
ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) Feature Source (%W) supports FDO join optimization"), fsIdStr.c_str()));
#endif
- m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+ m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select, m_options);
mgReader = SelectFdoJoin(resource, className, false);
}
else
@@ -162,7 +162,7 @@
#endif
// Perform the same select query as above, but route this through the FDO expression engine
// Slow maybe, but anything is faster than going via the GWS query engine.
- m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+ m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select, m_options);
mgReader = SelectFdoJoin(resource, className, true);
}
else
@@ -605,8 +605,17 @@
if (cnt <= 0)
return; // Nothing to do
+ bool bSupportsOrdering = m_command->SupportsSelectOrdering();
+ bool bExtended = m_command->IsExtended();
+ // Not supported? We can still support if it supports extended select. This may look like a bit of hack
+ // but the known implementations of FdoIExtendedSelect (SDF/SHP) will honor the ordering option if used
+ if (!bSupportsOrdering)
+ {
+ bSupportsOrdering = (cnt == 1) && bExtended;
+ }
+
// Ordering options are supplied but provider does not support it
- if (!m_command->SupportsSelectOrdering())
+ if (!bSupportsOrdering)
{
STRING message = MgServerFeatureUtil::GetMessage(L"MgOrderingOptionNotSupported");
@@ -615,23 +624,44 @@
throw new MgFeatureServiceException(L"MgServerSelectFeatures.ApplyOrderingOptions", __LINE__, __WFILE__, &arguments, L"", NULL);
}
- FdoPtr<FdoIdentifierCollection> fic = m_command->GetOrdering();
- CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyOrderingOptions");
+ if ((cnt == 1) && bExtended)
+ {
+ // Order option Asc or Desc (default is Asc)
+ FdoOrderingOption option = MgServerFeatureUtil::GetFdoOrderingOption(m_options->GetOrderOption());
+ STRING propertyName = properties->GetItem(0);
- // Order option Asc or Desc (default is Asc)
- FdoOrderingOption option = MgServerFeatureUtil::GetFdoOrderingOption(m_options->GetOrderOption());
- m_command->SetOrderingOption(option);
+ FdoPtr<FdoIdentifierCollection> fic = m_command->GetOrdering();
+ CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyOrderingOptions");
- for (INT32 i=0; i < cnt; i++)
+ // Order option Asc or Desc (default is Asc)
+ //
+ // With extended select, we still have to make sure the base ordering option is set
+ m_command->SetOrderingOption(option);
+ FdoPtr<FdoIdentifier> ident = FdoIdentifier::Create((FdoString*)propertyName.c_str());
+ fic->Add(ident);
+
+ m_command->SetExtendedOrderingOption((FdoString*)propertyName.c_str(), option);
+ }
+ else
{
- STRING propertyName = properties->GetItem(i);
+ FdoPtr<FdoIdentifierCollection> fic = m_command->GetOrdering();
+ CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyOrderingOptions");
- if (!propertyName.empty())
+ // Order option Asc or Desc (default is Asc)
+ FdoOrderingOption option = MgServerFeatureUtil::GetFdoOrderingOption(m_options->GetOrderOption());
+ m_command->SetOrderingOption(option);
+
+ for (INT32 i = 0; i < cnt; i++)
{
- FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
- CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyOrderingOptions");
+ STRING propertyName = properties->GetItem(i);
- fic->Add(fdoIden);
+ if (!propertyName.empty())
+ {
+ FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
+ CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyOrderingOptions");
+
+ fic->Add(fdoIden);
+ }
}
}
}
@@ -780,11 +810,11 @@
{
if (!isSelectAggregate)
{
- m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select);
+ m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_Select, m_options);
}
else
{
- m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_SelectAggregates);
+ m_command = MgFeatureServiceCommand::CreateCommand(resource, FdoCommandType_SelectAggregates, m_options);
}
CHECKNULL((MgFeatureServiceCommand*)m_command, L"MgServerSelectFeatures.CreateCommand");
}
Modified: trunk/MgDev/Server/src/UnitTesting/TestFeatureService.cpp
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestFeatureService.cpp 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/UnitTesting/TestFeatureService.cpp 2015-02-03 11:41:32 UTC (rev 8528)
@@ -1374,7 +1374,86 @@
}
}
+///----------------------------------------------------------------------------
+/// Test Case Description:
+///
+/// This test case exercises selecting features against a SDF feature source
+/// with ordering (not supported in capabilities, but allowed through extended
+/// select but only on a single property)
+///----------------------------------------------------------------------------
+void TestFeatureService::TestCase_SelectFeaturesSdfWithOrdering()
+{
+ try
+ {
+ MgServiceManager* serviceManager = MgServiceManager::GetInstance();
+ if (serviceManager == 0)
+ {
+ throw new MgNullReferenceException(L"TestFeatureService.TestCase_SelectFeatures", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+ Ptr<MgFeatureService> pService = dynamic_cast<MgFeatureService*>(serviceManager->RequestService(MgServiceType::FeatureService));
+ if (pService == 0)
+ {
+ throw new MgServiceNotAvailableException(L"TestFeatureService.TestCase_SelectFeatures", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ Ptr<MgResourceIdentifier> resource = new MgResourceIdentifier(L"Library://UnitTests/Data/Sheboygan_VotingDistricts.FeatureSource");
+ STRING className = L"VotingDistricts";
+
+ Ptr<MgFeatureQueryOptions> options = new MgFeatureQueryOptions();
+ Ptr<MgStringCollection> orderProps = new MgStringCollection();
+ orderProps->Add(L"ID");
+ orderProps->Add(L"NAME");
+ options->SetOrderingFilter(orderProps, MgOrderingOption::Descending);
+
+ //Invalid conditions for ordered select
+ CPPUNIT_ASSERT_THROW_MG(pService->SelectFeatures(resource, className, options), MgFeatureServiceException*);
+
+ orderProps->Clear();
+ orderProps->Add(L"ID");
+ options->SetOrderingFilter(orderProps, MgOrderingOption::Ascending);
+
+ STRING str;
+ //Now valid
+ Ptr<MgFeatureReader> reader = pService->SelectFeatures(resource, className, options);
+ while (reader->ReadNext())
+ {
+ str += reader->GetString(L"ID");
+ }
+ reader->Close();
+ CPPUNIT_ASSERT(str == L"12334456678");
+
+ orderProps->Clear();
+ orderProps->Add(L"ID");
+ options->SetOrderingFilter(orderProps, MgOrderingOption::Descending);
+
+ str.clear();
+ //Now valid
+ reader = pService->SelectFeatures(resource, className, options);
+ while (reader->ReadNext())
+ {
+ str += reader->GetString(L"ID");
+ }
+ reader->Close();
+ CPPUNIT_ASSERT(str == L"87665443321");
+ }
+ catch (MgException* e)
+ {
+ STRING message = e->GetDetails(TEST_LOCALE);
+ SAFE_RELEASE(e);
+ CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+ }
+ catch (FdoException* e)
+ {
+ FDO_SAFE_RELEASE(e);
+ CPPUNIT_FAIL("FdoException occurred");
+ }
+ catch (...)
+ {
+ throw;
+ }
+}
+
///----------------------------------------------------------------------------
/// Test Case Description:
///
Modified: trunk/MgDev/Server/src/UnitTesting/TestFeatureService.h
===================================================================
--- trunk/MgDev/Server/src/UnitTesting/TestFeatureService.h 2015-02-02 11:59:46 UTC (rev 8527)
+++ trunk/MgDev/Server/src/UnitTesting/TestFeatureService.h 2015-02-03 11:41:32 UTC (rev 8528)
@@ -39,6 +39,7 @@
CPPUNIT_TEST(TestCase_ApplySchema);
CPPUNIT_TEST(TestCase_SelectFeatures);
CPPUNIT_TEST(TestCase_SelectFeaturesWithXform);
+ CPPUNIT_TEST(TestCase_SelectFeaturesSdfWithOrdering);
CPPUNIT_TEST(TestCase_SelectAggregate);
CPPUNIT_TEST(TestCase_UpdateFeaturesInsert);
CPPUNIT_TEST(TestCase_UpdateFeaturesPartialFailure);
@@ -93,6 +94,7 @@
void TestCase_ApplySchema();
void TestCase_SelectFeatures();
void TestCase_SelectFeaturesWithXform();
+ void TestCase_SelectFeaturesSdfWithOrdering();
void TestCase_SelectAggregate();
void TestCase_UpdateFeaturesInsert();
void TestCase_UpdateFeaturesPartialFailure();
More information about the mapguide-commits
mailing list