[gdal-dev] ogr2ogr and RFC41

Martin Landa landa.martin at gmail.com
Sun Oct 26 08:10:48 PDT 2014


Hi,

2014-10-24 9:46 GMT+02:00 Martin Landa <landa.martin at gmail.com>:
>> So perhaps something like ?
>> --select *,!geom1,!attr1
>
> yes, it would be nice to have it... Martin

the attached patch shows a way, I am sure that it's possible to
simplily it. Anyway combination as (assuming that a source layer has
three geometry columns) seems to work:

$ ogr2ogr -f PostgreSQL -select '*' PG:dbname=vfr_10 PG:dbname=vfr
staty -overwrite

-> OK all attributes + geom1

$ ogr2ogr -f PostgreSQL -select '*,!geom1' PG:dbname=vfr_10
PG:dbname=vfr staty -overwrite

-> OK, all atributes + geom2

$ ogr2ogr -f PostgreSQL -select '*,!geom1,!geom2' PG:dbname=vfr_10
PG:dbname=vfr staty -overwrite

-> OK, all atributes + geom3

BTW, I would assume that if the destination datasource supports RFC41
than ogr2ogr transfers all geometry columns, but it doesn't seems to
be true, eg.:

$ ogrinfo PG:dbname=vfr staty | grep Geometry
Geometry (definicnibod): Point
Geometry (originalnihranice): Multi Polygon
Geometry (generalizovanehranice): Multi Polygon
Geometry Column 1 = definicnibod
Geometry Column 2 = originalnihranice
Geometry Column 3 = generalizovanehranice

$ ogr2ogr -f PostgreSQL PG:dbname=vfr_10 PG:dbname=vfr staty -overwrite

$ ogrinfo PG:dbname=vfr_10 staty | grep Geometry
Geometry: Unknown (any)
Geometry Column = GEOMETRY

Martin

-- 
Martin Landa * http://geo.fsv.cvut.cz/gwiki/Landa *
http://www.gismentors.eu/mentors/landa
-------------- next part --------------
Index: apps/ogr2ogr.cpp
===================================================================
--- apps/ogr2ogr.cpp	(revision 27908)
+++ apps/ogr2ogr.cpp	(working copy)
@@ -38,6 +38,7 @@
 #include "commonutils.h"
 #include <map>
 #include <vector>
+#include <algorithm>
 
 CPL_CVSID("$Id$");
 
@@ -76,6 +77,9 @@
     TargetLayerInfo  *psInfo;
 } AssociatedLayers;
 
+static std::vector<CPLString> FilterSelectFields(OGRFeatureDefn *poSrcFDefn,
+                                                 char **papszSelFields, bool);
+
 static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
                                                  const char* pszNewLayerName,
                                                  int bOverwrite,
@@ -2561,6 +2565,8 @@
     OGRFeatureDefn *poSrcFDefn;
     OGRFeatureDefn *poDstFDefn = NULL;
 
+    std::vector<CPLString> oSelFields;
+
     if( pszNewLayerName == NULL )
         pszNewLayerName = poSrcLayer->GetName();
 
@@ -2570,15 +2576,22 @@
     poSrcFDefn = poSrcLayer->GetLayerDefn();
 
 /* -------------------------------------------------------------------- */
+/*      Filter select fields (*, !col).                                 */
+/* -------------------------------------------------------------------- */
+    if (papszSelFields)
+        oSelFields = FilterSelectFields(poSrcFDefn, papszSelFields,
+                                        poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer));
+
+/* -------------------------------------------------------------------- */
 /*      Find requested geometry fields.                                 */
 /* -------------------------------------------------------------------- */
     std::vector<int> anRequestedGeomFields;
     int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
-    if (papszSelFields && !bAppend )
+    if (oSelFields.size() > 0 && !bAppend )
     {
-        for( int iField=0; papszSelFields[iField] != NULL; iField++)
+        for( size_t iField=0; iField < oSelFields.size(); iField++)
         {
-            int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
+            int iSrcField = poSrcFDefn->GetFieldIndex(oSelFields[iField]);
             if (iSrcField >= 0)
             {
                 /* do nothing */
@@ -2585,7 +2598,7 @@
             }
             else
             {
-                iSrcField = poSrcFDefn->GetGeomFieldIndex(papszSelFields[iField]);
+                iSrcField = poSrcFDefn->GetGeomFieldIndex(oSelFields[iField]);
                 if( iSrcField >= 0)
                 {
                     anRequestedGeomFields.push_back(iSrcField);
@@ -2593,7 +2606,7 @@
                 else
                 {
                     fprintf( stderr, "Field '%s' not found in source layer.\n",
-                            papszSelFields[iField] );
+                             oSelFields[iField].c_str() );
                     if( !bSkipFailures )
                         return NULL;
                 }
@@ -2797,8 +2810,8 @@
 /*      the selected fields, and in the order that they were            */
 /*      selected.                                                       */
 /* -------------------------------------------------------------------- */
-    int         nSrcFieldCount = poSrcFDefn->GetFieldCount();
-    int         iField, *panMap;
+    int      nSrcFieldCount = poSrcFDefn->GetFieldCount();
+    int      iField, *panMap;
 
     // Initialize the index-to-index map to -1's
     panMap = (int *) VSIMalloc( sizeof(int) * nSrcFieldCount );
@@ -2834,14 +2847,14 @@
             }
         }
     }
-    else if (papszSelFields && !bAppend )
+    else if (oSelFields.size() > 0 && !bAppend )
     {
         int  nDstFieldCount = 0;
         if (poDstFDefn)
             nDstFieldCount = poDstFDefn->GetFieldCount();
-        for( iField=0; papszSelFields[iField] != NULL; iField++)
+        for( iField=0; iField < (int) oSelFields.size(); iField++)
         {
-            int iSrcField = poSrcFDefn->GetFieldIndex(papszSelFields[iField]);
+            int iSrcField = poSrcFDefn->GetFieldIndex(oSelFields[iField]);
             if (iSrcField >= 0)
             {
                 OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
@@ -2920,9 +2933,9 @@
                 const char* pszFieldName =
                     poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
                 int bFieldRequested = FALSE;
-                for( iField=0; papszSelFields[iField] != NULL; iField++)
+                for( iField=0; iField < (int) oSelFields.size(); iField++)
                 {
-                    if (EQUAL(pszFieldName, papszSelFields[iField]))
+                    if (EQUAL(pszFieldName, oSelFields[iField]))
                     {
                         bFieldRequested = TRUE;
                         break;
@@ -3658,3 +3671,104 @@
 
     return TRUE;
 }
+
+/* -------------------------------------------------------------------- */
+/*      Filter select fields (*, !col).                                 */
+/* -------------------------------------------------------------------- */
+std::vector<CPLString> FilterSelectFields(OGRFeatureDefn *poSrcFDefn, char **papszSelFields,
+                                          bool bCreateGeom)
+{
+    std::vector<CPLString> oSelFields;
+    int iSrcField, nFCount;
+    const char *pszSrcFieldName;
+    
+    // first pass - append requested columns (*)
+    for( int iField = 0; papszSelFields[iField] != NULL; iField++)
+    {
+        const char *pszFieldName = papszSelFields[iField];
+        if( EQUAL(pszFieldName, "*" ) )
+        {
+            // append all attributes
+            nFCount = poSrcFDefn->GetFieldCount();
+            for( iSrcField = 0; iSrcField < nFCount; iSrcField++ )
+            {
+                pszSrcFieldName = poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
+                if( std::find( oSelFields.begin(), oSelFields.end(),
+                                pszFieldName) == oSelFields.end() )
+                    oSelFields.push_back( pszSrcFieldName );
+            }
+            
+            // append also geometrie attributes
+            nFCount = poSrcFDefn->GetGeomFieldCount();
+            for( iSrcField = 0; iSrcField < nFCount; iSrcField++ )
+            {
+                pszSrcFieldName = poSrcFDefn->GetGeomFieldDefn(iSrcField)->GetNameRef();
+                if( std::find( oSelFields.begin(), oSelFields.end(),
+                                pszFieldName) == oSelFields.end() )
+                    oSelFields.push_back( pszSrcFieldName  );
+            }
+        }
+        else if( pszFieldName && pszFieldName[0] == '!' )
+        {
+            continue; // skip
+        }
+        else
+        {
+          if( std::find( oSelFields.begin(), oSelFields.end(),
+                         pszFieldName) == oSelFields.end() )
+              oSelFields.push_back(pszFieldName);
+        }
+    }
+
+    // second pass - include all geometry attributes 
+    nFCount = poSrcFDefn->GetGeomFieldCount();
+    for( iSrcField = 0; iSrcField < nFCount; iSrcField++ )
+    {
+        pszSrcFieldName = poSrcFDefn->GetGeomFieldDefn(iSrcField)->GetNameRef();
+        if( std::find( oSelFields.begin(), oSelFields.end(),
+                       pszSrcFieldName) == oSelFields.end() )
+            oSelFields.push_back( pszSrcFieldName );
+    }
+
+    // third pass - pop requested columns (!col)
+    for( int iField = 0; papszSelFields[iField] != NULL; iField++)
+    {
+        pszSrcFieldName = papszSelFields[iField];  
+        if( pszSrcFieldName && pszSrcFieldName[0] == '!' )
+        {
+            CPLString osFieldName(pszSrcFieldName);
+            osFieldName.erase( osFieldName.begin());  
+
+            std::vector<CPLString>::iterator iItem = std::remove( oSelFields.begin(),
+                                                                  oSelFields.end(), osFieldName );
+            oSelFields.erase( iItem, oSelFields.end() );
+        }
+    }
+
+    // fourth pass - check multiple geometry attributes
+    if ( !bCreateGeom )
+    {
+        bool bFirst = TRUE;
+        nFCount = poSrcFDefn->GetGeomFieldCount();
+        for( iSrcField = 0; iSrcField < nFCount; iSrcField++ )
+        {
+            CPLString osFieldName(poSrcFDefn->GetGeomFieldDefn(iSrcField)->GetNameRef());
+
+            if( std::find( oSelFields.begin(), oSelFields.end(),
+                           osFieldName) != oSelFields.end() )
+            {
+                
+                if (bFirst)
+                    bFirst = FALSE;
+                else
+                {
+                    std::vector<CPLString>::iterator iItem = std::remove( oSelFields.begin(),
+                                                                          oSelFields.end(), osFieldName );
+                    oSelFields.erase( iItem, oSelFields.end() ); 
+                }
+            }
+        }
+    }
+
+    return oSelFields;
+}


More information about the gdal-dev mailing list