[mapguide-commits] r7396 - branches/2.5/MgDev/Server/src/Services/Feature

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Mar 14 06:13:18 PDT 2013


Author: jng
Date: 2013-03-14 06:13:18 -0700 (Thu, 14 Mar 2013)
New Revision: 7396

Modified:
   branches/2.5/MgDev/Server/src/Services/Feature/SelectCommand.cpp
   branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.cpp
   branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.h
   branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp
   branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.h
Log:
#2214: Fix two issues with our RFC123 implementation:
 1. Un-selectable layers due to the MgFeatureReader not presenting a MgClassDefinition with identity properties
 2. Selects with an explicit property list failing due to not doing the [property_alias] -> [class_alias].[propertyName] reverse mapping for the underlying FDO join query

Modified: branches/2.5/MgDev/Server/src/Services/Feature/SelectCommand.cpp
===================================================================
--- branches/2.5/MgDev/Server/src/Services/Feature/SelectCommand.cpp	2013-03-13 14:12:41 UTC (rev 7395)
+++ branches/2.5/MgDev/Server/src/Services/Feature/SelectCommand.cpp	2013-03-14 13:13:18 UTC (rev 7396)
@@ -415,16 +415,26 @@
 
     MG_FEATURE_SERVICE_TRY()
 
+#ifdef DEBUG_FDO_JOIN
+    FdoPtr<FdoIdentifierCollection> cmdPropNames = m_command->GetPropertyNames();
+    for (FdoInt32 i = 0; i < cmdPropNames->GetCount(); i++)
+    {
+        FdoPtr<FdoIdentifier> ident = cmdPropNames->GetItem(i);
+        STRING idStr = ident->ToString();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [FdoISelect]: (%W)"), idStr.c_str()));
+    }
+#endif
+
     FdoPtr<FdoIFeatureReader> fdoReader = m_command->Execute();
     if (bForceOneToOne)
     {
         FdoPtr<FdoStringCollection> names = MgServerFeatureUtil::MgToFdoStringCollection(idPropNames, false);
         FdoPtr<FdoIFeatureReader> forcedReader = new MgFdoForcedOneToOneFeatureReader(fdoReader, names); 
-        ret = new MgServerFeatureReader(m_connection, forcedReader);
+        ret = new MgServerFeatureReader(m_connection, forcedReader, idPropNames);
     }
     else
     {
-        ret = new MgServerFeatureReader(m_connection, fdoReader);
+        ret = new MgServerFeatureReader(m_connection, fdoReader, idPropNames);
     }
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgSelectCommand.ExecuteJoined")
 

Modified: branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.cpp
===================================================================
--- branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.cpp	2013-03-13 14:12:41 UTC (rev 7395)
+++ branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.cpp	2013-03-14 13:13:18 UTC (rev 7396)
@@ -28,7 +28,7 @@
 ///</summary>
 ///<param name="byteSource">Byte  source object</param>
 ///
-MgServerFeatureReader::MgServerFeatureReader(MgServerFeatureConnection* connection, FdoIFeatureReader* fdoReader)
+MgServerFeatureReader::MgServerFeatureReader(MgServerFeatureConnection* connection, FdoIFeatureReader* fdoReader, MgStringCollection* forceIdProps)
 {
     MG_FEATURE_SERVICE_TRY()
 
@@ -36,6 +36,7 @@
     m_featureSet = NULL;
     m_connection = SAFE_ADDREF(connection);
     m_fdoReader = FDO_SAFE_ADDREF(fdoReader);
+    m_forceIdProps = SAFE_ADDREF(forceIdProps); //This is only passed in for select queries that involve the FDO Join APIs
     m_removeFromPoolOnDestruction = false;
 
     // The reader takes ownership of the FDO connection
@@ -140,6 +141,39 @@
         // Convert FdoClassDefinition to MgClassDefinition
         m_classDef = MgServerFeatureUtil::GetMgClassDefinition(fdoClassDefinition, true);
         CHECKNULL(m_classDef.p, L"MgServerGetFeatures.GetFeatures");
+
+        // The class definition presented by a FDO reader from a join select query will probably
+        // not contain any identity properties, thereby violating our golden rule of selection (no id props = unselectable)
+        // so for such queries executed by MapGuide, we pass this list of identity properties on to this reader (sourced
+        // with the identity properties from the "primary" class definition) so that we can "rewrite" the converted MgClassDefinition
+        if (NULL != m_forceIdProps && m_forceIdProps->GetCount() > 0)
+        {
+            Ptr<MgPropertyDefinitionCollection> clsProps = m_classDef->GetProperties();
+            Ptr<MgPropertyDefinitionCollection> clsIdProps = m_classDef->GetIdentityProperties();
+
+            // This is most likely empty, but we're overwriting this anyway, so clear it
+            clsIdProps->Clear();
+
+            // Copy across any properties from the explicity identity property name list
+            for (INT32 i = 0; i < m_forceIdProps->GetCount(); i++)
+            {
+                STRING propName = m_forceIdProps->GetItem(i);
+                INT32 pidx = clsProps->IndexOf(propName);
+                if (pidx >= 0)
+                {
+                    Ptr<MgPropertyDefinition> p = clsProps->GetItem(pidx);
+                    clsIdProps->Add(p);
+                } //else should we care about correctness?
+            }
+        }
+
+#ifdef DEBUG_FDO_JOIN
+        Ptr<MgPropertyDefinitionCollection> idProps = m_classDef->GetIdentityProperties();
+        Ptr<MgPropertyDefinitionCollection> props = m_classDef->GetProperties();
+        INT32 idCount = idProps->GetCount();
+        INT32 propCount = props->GetCount();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [MgFeatureReader::GetClassDefinition] %d props, %d identity props"), propCount, idCount));
+#endif
     }
 
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerFeatureReader.GetClassDefinition")
@@ -176,6 +210,39 @@
         // Convert FdoClassDefinition to MgClassDefinition
         m_classDef = MgServerFeatureUtil::GetMgClassDefinition(fdoClassDefinition, false);
         CHECKNULL(m_classDef.p, L"MgServerGetFeatures.GetFeatures");
+
+        // The class definition presented by a FDO reader from a join select query will probably
+        // not contain any identity properties, thereby violating our golden rule of selection (no id props = unselectable)
+        // so for such queries executed by MapGuide, we pass this list of identity properties on to this reader (sourced
+        // with the identity properties from the "primary" class definition) so that we can "rewrite" the converted MgClassDefinition
+        if (NULL != m_forceIdProps && m_forceIdProps->GetCount() > 0)
+        {
+            Ptr<MgPropertyDefinitionCollection> clsProps = m_classDef->GetProperties();
+            Ptr<MgPropertyDefinitionCollection> clsIdProps = m_classDef->GetIdentityProperties();
+
+            // This is most likely empty, but we're overwriting this anyway, so clear it
+            clsIdProps->Clear();
+
+            // Copy across any properties from the explicity identity property name list
+            for (INT32 i = 0; i < m_forceIdProps->GetCount(); i++)
+            {
+                STRING propName = m_forceIdProps->GetItem(i);
+                INT32 pidx = clsProps->IndexOf(propName);
+                if (pidx >= 0)
+                {
+                    Ptr<MgPropertyDefinition> p = clsProps->GetItem(pidx);
+                    clsIdProps->Add(p);
+                } //else should we care about correctness?
+            }
+        }
+
+#ifdef DEBUG_FDO_JOIN
+        Ptr<MgPropertyDefinitionCollection> idProps = m_classDef->GetIdentityProperties();
+        Ptr<MgPropertyDefinitionCollection> props = m_classDef->GetProperties();
+        INT32 idCount = idProps->GetCount();
+        INT32 propCount = props->GetCount();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [MgFeatureReader::GetClassDefinitionNoXml] %d props, %d identity props"), propCount, idCount));
+#endif
     }
 
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerFeatureReader.GetClassDefinitionNoXml")

Modified: branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.h
===================================================================
--- branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.h	2013-03-13 14:12:41 UTC (rev 7395)
+++ branches/2.5/MgDev/Server/src/Services/Feature/ServerFeatureReader.h	2013-03-14 13:13:18 UTC (rev 7396)
@@ -555,7 +555,7 @@
 
     MgServerFeatureReader();
 
-    MgServerFeatureReader(MgServerFeatureConnection* connection, FdoIFeatureReader* fdoReader);
+    MgServerFeatureReader(MgServerFeatureConnection* connection, FdoIFeatureReader* fdoReader, MgStringCollection* forceIdProps = NULL);
     ~MgServerFeatureReader();
 
     virtual void Dispose();
@@ -574,6 +574,7 @@
     Ptr<MgServerFeatureConnection> m_connection;
     FdoIFeatureReader* m_fdoReader;
     bool m_removeFromPoolOnDestruction;
+    Ptr<MgStringCollection> m_forceIdProps;
 
 CLASS_ID:
     static const INT32 m_cls_id = PlatformBase_FeatureService_FeatureReader;

Modified: branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp
===================================================================
--- branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp	2013-03-13 14:12:41 UTC (rev 7395)
+++ branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.cpp	2013-03-14 13:13:18 UTC (rev 7396)
@@ -365,9 +365,6 @@
     if (cnt <= 0)
         return; // Nothing to do
 
-    //TODO: Need to check if FDO join optimization is supported, and whether this contains prefixed
-    //secondary properties.
-
     FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
     CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyClassProperties");
 
@@ -382,7 +379,58 @@
     }
 }
 
+void MgServerSelectFeatures::ApplyClassPropertiesForFdoJoin(CREFSTRING primaryAlias, CREFSTRING secondaryAlias, CREFSTRING secondaryPrefix)
+{
+    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyClassPropertiesForFdoJoin");
+    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyClassPropertiesForFdoJoin");
 
+    Ptr<MgStringCollection> properties = m_options->GetClassProperties();
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyClassPropertiesForFdoJoin");
+
+    //If we're given an explicit property list, it will be whatever is presented by the Extended Feature Class
+    //So we have to "re-shape" this property list into a aliased qualified property list like the standard FDO
+    //join query. Basically, were doing a reverse property mapping.
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING propertyName = properties->GetItem(i);
+
+        //Check if this name starts with prefix
+        //
+        // If it does, it's a secondary join property and should be re-aliased as [secondaryAlias].[propertyNameWithoutPrefix]
+        // Otherwise, it should be re-aliased as [primaryAlias].[propertyNameAsIs]
+        STRING reAliasedPropName;
+        if (propertyName.compare(0, secondaryPrefix.length(), secondaryPrefix) == 0)
+        {
+            reAliasedPropName = secondaryAlias;
+            reAliasedPropName += L".";
+            reAliasedPropName += propertyName.substr(secondaryPrefix.length());
+        }
+        else
+        {
+            reAliasedPropName = primaryAlias;
+            reAliasedPropName += L".";
+            reAliasedPropName += propertyName;
+        }
+
+        //This will now be [alias].[reAliasedPropertyName] AS [propertyName]
+        FdoPtr<FdoExpression> expr = FdoExpression::Parse((FdoString*)reAliasedPropName.c_str());
+        FdoPtr<FdoComputedIdentifier> fdoIden = FdoComputedIdentifier::Create((FdoString*)propertyName.c_str(), expr);
+        CHECKNULL((FdoComputedIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyClassPropertiesForFdoJoin");
+
+        fic->Add(fdoIden);
+    }
+}
+
 // Computed properties
 void MgServerSelectFeatures::ApplyComputedProperties()
 {
@@ -465,7 +513,7 @@
     if (!filterText.empty())
     {
         regularFilter = FdoFilter::Parse(filterText.c_str());
-        #ifdef _DEBUG
+        #if defined(_DEBUG) || defined(DEBUG_FDO_JOIN)
         ACE_DEBUG((LM_ERROR, ACE_TEXT("FILTER(size=%d):\n%W\n\n"), filterText.length(), filterText.c_str()));
         #endif
     }
@@ -1917,7 +1965,11 @@
     }
 
     CHECKNULL(extension, L"MgServerSelectFeatures.SelectFdoJoin");
-    m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
+    FdoString* clsName = extension->GetFeatureClass().c_str();
+    m_command->SetFeatureClassName(clsName);
+#ifdef DEBUG_FDO_JOIN
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FdoISelect] Set primary feature class: %W"), clsName));
+#endif
     MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
     CHECKNULL(relates, L"MgServerSelectFeatures.SelectFdoJoin");
     MdfModel::AttributeRelate* relate = relates->GetAt(0);
@@ -1955,11 +2007,9 @@
         bool bAppliedProperties = false;
         if (m_options != NULL)
         {
-            //ApplyClassProperties();
             ApplyComputedProperties();
             // TODO: We need to find out if there are any filters involving the secondary side
             ApplyFilter();
-            // ApplySpatialFilter();
             ApplyOrderingOptions();
             // We don't apply aggregate options here because these go through the FDO Expression Engine
             ApplyAggregateOptions(isAggregate);
@@ -1970,7 +2020,7 @@
             Ptr<MgStringCollection> props = m_options->GetClassProperties();
             if (props->GetCount() > 0)
             {
-                ApplyClassProperties();
+                ApplyClassPropertiesForFdoJoin(primaryAlias, secondaryAlias, prefix);
                 bAppliedProperties = true;
             }
         }
@@ -2211,7 +2261,6 @@
         STRING idName = prefix + propDef->GetName();
         //[alias].[propertyName] AS [prefix][propertyName]
         FdoPtr<FdoComputedIdentifier> compId = FdoComputedIdentifier::Create(idName.c_str(), expr);
-
         propNames->Add(compId);
     }
 

Modified: branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.h
===================================================================
--- branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.h	2013-03-13 14:12:41 UTC (rev 7395)
+++ branches/2.5/MgDev/Server/src/Services/Feature/ServerSelectFeatures.h	2013-03-14 13:13:18 UTC (rev 7396)
@@ -96,6 +96,7 @@
     bool m_bUseFdoJoinOptimization;
 
     // FDO join optimization
+    void ApplyClassPropertiesForFdoJoin(CREFSTRING primaryAlias, CREFSTRING secondaryAlias, CREFSTRING secondaryPrefix);
     bool IsFunctionOnPrimaryProperty(FdoFunction* function, FdoIConnection* conn, CREFSTRING schemaName, CREFSTRING className);
     bool SupportsFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);
     MgReader* SelectFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);



More information about the mapguide-commits mailing list