[mapguide-commits] r7340 - in sandbox/adsk/2.3r.sce: Common/PlatformBase/MapLayer Server/src/Services/Feature Server/src/Services/Mapping Server/src/Services/Rendering
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Sun Jan 27 17:04:05 PST 2013
Author: hubu
Date: 2013-01-27 17:04:04 -0800 (Sun, 27 Jan 2013)
New Revision: 7340
Modified:
sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.cpp
sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.h
sandbox/adsk/2.3r.sce/Server/src/Services/Feature/SelectCommand.cpp
sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.cpp
sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.h
sandbox/adsk/2.3r.sce/Server/src/Services/Rendering/ServerRenderingService.cpp
Log:
Submit on behalf of Andy Zhang
This is special submission only for SCE customer. SCE uses Teradata database and encounters significant performance issue especially when selecting features. After investigation, we found that Teradata has performance issue when processing long SQL statements. When selecting features, the SQL statement is like 'SELECT col1, col2, ... FROM table WHERE key=xxx OR key=yyy OR ...'. If we select a large dataset, there might be thousands of ORs in the SQL statement. The performance is very bad in this case.
Therefore, we create a special hotfix for Teradata. We still use SQL 'SELECT col1, col2, ... FROM table WHERE geomCondition' to render the selection image and fill out the selection panel. The APIs SelectionBase::SetGeometry() and SelectionBase::GetGeometry() are added. If the web-tier side code sets the geometry filter of the selection, Sever side will parse this geometry filter and generate SQL statement according to the geometry filter. Then the SQL statement will not be too long. This change improves Teradata's selection performance significantly in my test. The time of selecting 10,000 features is from 8m to 50s.
We created a new branch 2.3r.sce for this change. It is based on 2.3 RTM. All the related code are submitted to this new branch. The changes will not impact other users.
Modified: sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.cpp
===================================================================
--- sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.cpp 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.cpp 2013-01-28 01:04:04 UTC (rev 7340)
@@ -25,14 +25,14 @@
/////////////////////////////////////////
// Dummy constructor for Ptr<> template
//
-MgSelectionBase::MgSelectionBase()
+MgSelectionBase::MgSelectionBase() : m_geometry(L"")
{
m_stream = new MgMemoryStreamHelper();
}
// Initialize selection generation from a map
-MgSelectionBase::MgSelectionBase(MgMapBase* map)
+MgSelectionBase::MgSelectionBase(MgMapBase* map) : m_geometry(L"")
{
m_map = SAFE_ADDREF(map);
m_stream = new MgMemoryStreamHelper();
@@ -40,7 +40,7 @@
// Initialize selection from a map and xml selection
-MgSelectionBase::MgSelectionBase(MgMapBase* map, CREFSTRING xmlSelectionString)
+MgSelectionBase::MgSelectionBase(MgMapBase* map, CREFSTRING xmlSelectionString) : m_geometry(L"")
{
m_map = SAFE_ADDREF(map);
m_stream = new MgMemoryStreamHelper();
@@ -816,17 +816,22 @@
STRING clsName = layer->GetFeatureClassName();
STRING geomName = layer->GetFeatureGeometryName();
- STRING filterText = this->GenerateFilter(layer, clsName);
+ Ptr<MgStringCollection> filters = GenerateFilters(layer, clsName, 30000 /* magic number */);
+ INT32 numFilter = (NULL == filters)? 0 : filters->GetCount();
- Ptr<MgEnvelope> clsEnv = GetFeatureExtents(featureService, featureResId, clsName, filterText, geomName);
- if (env != NULL)
+ for (INT32 j = 0; j < numFilter; ++j)
{
- env->ExpandToInclude(clsEnv);
+ STRING filterText = filters->GetItem(j);
+ Ptr<MgEnvelope> clsEnv = GetFeatureExtents(featureService, featureResId, clsName, filterText, geomName);
+ if (env != NULL)
+ {
+ env->ExpandToInclude(clsEnv);
+ }
+ else
+ {
+ env = clsEnv.Detach();
+ }
}
- else
- {
- env = clsEnv.Detach();
- }
}
}
return env.Detach();
@@ -948,10 +953,21 @@
m_map = SAFE_ADDREF((MgMapBase*)map);
}
+STRING MgSelectionBase::GetGeometry()
+{
+ return m_geometry;
+}
+void MgSelectionBase::SetGeometry(CREFSTRING geometry)
+{
+ m_geometry = geometry;
+}
+
void MgSelectionBase::Serialize(MgStream* stream)
{
stream->WriteInt32((INT32)m_selections.size());
+ Ptr<MgStreamHelper> helper = stream->GetStreamHelper();
+ helper->WriteString(m_geometry);
for(SelectionMap::iterator lIter = m_selections.begin(); lIter != m_selections.end(); ++lIter)
{
stream->WriteString(lIter->first);
@@ -973,7 +989,8 @@
{
INT32 lMapCount;
stream->GetInt32(lMapCount);
-
+ Ptr<MgStreamHelper> helper = stream->GetStreamHelper();
+ helper->GetString(m_geometry);
for(INT32 i = 0; i < lMapCount; i++)
{
SelectedClassMap* classMap = new SelectedClassMap;
Modified: sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.h
===================================================================
--- sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.h 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Common/PlatformBase/MapLayer/SelectionBase.h 2013-01-28 01:04:04 UTC (rev 7340)
@@ -393,6 +393,27 @@
///
STRING GenerateFilter(MgLayerBase* layer, CREFSTRING className);
+ //////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Generates a collection of FDO filter strings for the selections
+ /// of the specified layer and class
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// string GenerateFilters(MgLayerBase layer, string className, int selectionSize);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// String GenerateFilters(MgLayerBase layer, String className, int selectionSize);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// string GenerateFilters(MgLayerBase layer, string className, int selectionSize);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the collection of FDO filter strings
+ ///
+ MgStringCollection* GenerateFilters(MgLayerBase* layer, CREFSTRING className, INT32 selectionSize);
+
///////////////////////////////////////////////////////////////////////////
/// \brief
/// Gets the extents of the selection set.
@@ -514,18 +535,37 @@
///
STRING GetResourceName(CREFSTRING sessionId, CREFSTRING mapName);
-INTERNAL_API:
-
- //////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
/// \brief
- /// Generate a collection of FDO filter strings for the selections
- /// of the specified layer and class.
+ /// Returns the geometry filter of the selection.
///
/// \return
- /// Collection of FDO filter strings.
+ /// Geometry filter in WKT format.
///
- MgStringCollection* GenerateFilters(MgLayerBase* layer, CREFSTRING className, INT32 selectionSize);
+ STRING GetGeometry();
+ /////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the geometry filter the selection
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// void SetGeometry(string geometry);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// void SetGeometry(String geometry);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// void SetGeometry(string geometry)
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param geometry (String/string)
+ /// A string that specifies geometry filter in WKT format
+ ///
+ void SetGeometry(CREFSTRING geometry);
+
+INTERNAL_API:
+
//////////////////////////////////////////////////////////////////
/// \brief
/// Serialize data to a stream
@@ -622,6 +662,7 @@
SelectionMap m_selections;
Ptr<MgMapBase> m_map;
MgMemoryStreamHelper* m_stream;
+ STRING m_geometry;
};
/// \}
Modified: sandbox/adsk/2.3r.sce/Server/src/Services/Feature/SelectCommand.cpp
===================================================================
--- sandbox/adsk/2.3r.sce/Server/src/Services/Feature/SelectCommand.cpp 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Server/src/Services/Feature/SelectCommand.cpp 2013-01-28 01:04:04 UTC (rev 7340)
@@ -28,7 +28,7 @@
#include "FdoReaderCollection.h"
// The maximum size of the subfilter for a selection query. Tune this value for optimal selection perfomance.
-#define MG_MAX_SUBFILTER_SIZE 250
+#define MG_MAX_SUBFILTER_SIZE 1000
MgSelectCommand::MgSelectCommand(MgResourceIdentifier* resource)
{
Modified: sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.cpp
===================================================================
--- sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.cpp 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.cpp 2013-01-28 01:04:04 UTC (rev 7340)
@@ -82,7 +82,8 @@
const wchar_t* overrideFilter,
MgCoordinateSystem* mapCs,
MgCoordinateSystem* layerCs,
- TransformCache* cache)
+ TransformCache* cache,
+ bool spatialSelection)
{
#ifdef _DEBUG
long dwStart = GetTickCount();
@@ -181,7 +182,23 @@
//the FDO SHP provider. There are no bad side effects of this as long
//as override filters are only used to select features with specific IDs
//like they currently are.
- options->SetFilter(overrideFilter);
+ if (spatialSelection)
+ {
+ MgWktReaderWriter wktReader;
+ Ptr<MgGeometry> geometry = wktReader.Read(overrideFilter, trans);
+ if (!geom.empty())
+ {
+ //geometry providers -> we want an envelope intersects.
+ //If not, we need intersects. We should parse and check capabilities
+ //if we are to be really thorough, but we also do have a
+ //a more general query if the spatial fails
+ options->SetSpatialFilter(geom, geometry, MgFeatureSpatialOperations::EnvelopeIntersects);
+ }
+ if (!vl->GetFilter().empty())
+ options->SetFilter(vl->GetFilter());
+ }
+ else
+ options->SetFilter(overrideFilter);
}
else
{
@@ -364,7 +381,8 @@
bool checkRefreshFlag,
double scale,
bool selection,
- bool extractColors)
+ bool extractColors,
+ bool spatialSelection)
{
#ifdef _DEBUG
long dwStart = GetTickCount();
@@ -382,7 +400,7 @@
Ptr<MgLayerBase> mapLayer = layers->GetItem(i);
//don't send data if layer is not currently visible
- if ((!selection) && (!mapLayer->IsVisible()))
+ if (!mapLayer->IsVisible())
continue;
//don't send data if the refresh flag is not set
@@ -556,7 +574,7 @@
#endif
// create the reader we'll use
- rsReader = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, layerCs, item);
+ rsReader = ExecuteFeatureQuery(svcFeature, extent, vl, overrideFilter.c_str(), dstCs, layerCs, item, spatialSelection);
// create an automatic FdoPtr around the reader
FdoPtr<FdoIFeatureReader> fdoReader = (NULL == rsReader) ? NULL : rsReader->GetInternalReader();
Modified: sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.h
===================================================================
--- sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.h 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Server/src/Services/Mapping/MappingUtil.h 2013-01-28 01:04:04 UTC (rev 7340)
@@ -60,7 +60,8 @@
bool checkRefreshFlag,
double scale,
bool selection = false,
- bool extractColors = false);
+ bool extractColors = false,
+ bool spatialSelection = false);
static RSMgFeatureReader* ExecuteFeatureQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
@@ -68,7 +69,8 @@
const wchar_t* overrideFilter,
MgCoordinateSystem* mapCs,
MgCoordinateSystem* layerCs,
- TransformCache* cache);
+ TransformCache* cache,
+ bool spatialSelection = false);
static RSMgFeatureReader* ExecuteRasterQuery(MgFeatureService* svcFeature,
RS_Bounds& extent,
Modified: sandbox/adsk/2.3r.sce/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/adsk/2.3r.sce/Server/src/Services/Rendering/ServerRenderingService.cpp 2013-01-25 02:03:29 UTC (rev 7339)
+++ sandbox/adsk/2.3r.sce/Server/src/Services/Rendering/ServerRenderingService.cpp 2013-01-28 01:04:04 UTC (rev 7340)
@@ -926,6 +926,10 @@
if (selection && (behavior & MgRenderingOptions::RenderSelection))
{
Ptr<MgReadOnlyLayerCollection> selLayers = selection->GetLayers();
+ bool spatialSelection = false;
+ STRING geom = selection->GetGeometry();
+ if (wcscmp(geom.c_str(), L"") != 0)
+ spatialSelection = true;
#ifdef _DEBUG
printf("MgServerRenderingService::RenderMapInternal() - Layers:%d Selection Layers:%d\n", tempLayers.p? tempLayers->GetCount() : 0, selLayers.p? selLayers->GetCount() : 0);
@@ -958,21 +962,28 @@
for (int s=0; s<selLayers->GetCount(); s++)
{
Ptr<MgLayerBase> selLayer = selLayers->GetItem(s);
-
- // generate a filter for the selected features
- Ptr<MgStringCollection> filters = selection->GenerateFilters(
- selLayer, selLayer->GetFeatureClassName(), m_renderSelectionBatchSize);
- INT32 numFilter = (NULL == filters)? 0 : filters->GetCount();
-
- for (INT32 i = 0; i < numFilter; ++i)
+ if (spatialSelection)
{
- overrideFilters->Add(filters->GetItem(i));
+ overrideFilters->Add(geom);
modLayers->Add(selLayer);
}
+ else
+ {
+ // generate a filter for the selected features
+ Ptr<MgStringCollection> filters = selection->GenerateFilters(
+ selLayer, selLayer->GetFeatureClassName(), m_renderSelectionBatchSize);
+ INT32 numFilter = (NULL == filters)? 0 : filters->GetCount();
+
+ for (INT32 i = 0; i < numFilter; ++i)
+ {
+ overrideFilters->Add(filters->GetItem(i));
+ modLayers->Add(selLayer);
+ }
+ }
}
MgMappingUtil::StylizeLayers(m_svcResource, m_svcFeature, m_svcDrawing, m_pCSFactory, map,
- modLayers, overrideFilters, &ds, dr, dstCs, false, false, scale, (behavior & MgRenderingOptions::KeepSelection) != 0);
+ modLayers, overrideFilters, &ds, dr, dstCs, false, false, scale, (behavior & MgRenderingOptions::KeepSelection) != 0, false, spatialSelection);
// Set selection mode to false to avoid affecting following code
dr->SetRenderSelectionMode(false);
More information about the mapguide-commits
mailing list