Permalink
Browse files

[OGR] Fix support for Spatialite views

  • Loading branch information...
rouault committed Jul 26, 2016
1 parent b39fd15 commit 58ce9c453b67eb2fb73e32dcfb0bb5c025ab0458
View
@@ -1660,7 +1660,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}
char *select = NULL;
- char* pszTableName = NULL;
+ char* pszSpatialFilterTableName = NULL;
+ char* pszMainTableName = NULL;
+ char* pszRowId = NULL;
bool bIsOKForSQLCompose = true;
// In the case of a SQLite DB, check that we can identify the
@@ -1685,13 +1687,14 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
strstr(pszIter, " order by ") == NULL && strstr(pszIter, " ORDER BY ") == NULL)
{
bIsOKForSQLCompose = true;
- pszTableName = msStrdup(pszBeginningOfTable);
- pszTableName[pszIter - pszBeginningOfTable] = '\0';
+ pszMainTableName = msStrdup(pszBeginningOfTable);
+ pszMainTableName[pszIter - pszBeginningOfTable] = '\0';
+ pszSpatialFilterTableName = msStrdup(pszMainTableName);
char* pszRequest = NULL;
pszRequest = msStringConcatenate(pszRequest,
"SELECT * FROM sqlite_master WHERE type = 'table' AND name = lower('");
- pszRequest = msStringConcatenate(pszRequest, pszTableName);
+ pszRequest = msStringConcatenate(pszRequest, pszMainTableName);
pszRequest = msStringConcatenate(pszRequest, "')");
OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
msFree(pszRequest);
@@ -1708,6 +1711,32 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
{
select = msStrdup(psInfo->pszLayerDef);
}
+ else
+ {
+ // Test if it is a spatial view
+ pszRequest = msStringConcatenate(NULL,
+ "SELECT f_table_name, view_rowid FROM views_geometry_columns WHERE view_name = lower('");
+ pszRequest = msStringConcatenate(pszRequest, pszMainTableName);
+ pszRequest = msStringConcatenate(pszRequest, "')");
+ CPLPushErrorHandler(CPLQuietErrorHandler);
+ OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+ CPLPopErrorHandler();
+ msFree(pszRequest);
+
+ if( hLayer )
+ {
+ OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+ bIsOKForSQLCompose = (hFeature != NULL);
+ if( hFeature )
+ {
+ msFree(pszSpatialFilterTableName);
+ pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) );
+ pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) );
+ OGR_F_Destroy(hFeature);
+ }
+ OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+ }
+ }
}
}
}
@@ -1732,7 +1761,46 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
}
if( bIsOKForSQLCompose )
- pszTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+ {
+ pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+ pszSpatialFilterTableName = msStrdup(pszMainTableName);
+ }
+ else
+ {
+ // Test if it is a spatial view
+ pszRequest = msStringConcatenate(NULL,
+ "SELECT f_table_name, view_rowid FROM views_geometry_columns WHERE view_name = lower('");
+ pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+ pszRequest = msStringConcatenate(pszRequest, "')");
+ CPLPushErrorHandler(CPLQuietErrorHandler);
+ OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+ CPLPopErrorHandler();
+ msFree(pszRequest);
+
+ if( hLayer )
+ {
+ OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+ bIsOKForSQLCompose = (hFeature != NULL);
+ if( hFeature )
+ {
+ pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+ pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) );
+ pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) );
+ OGR_F_Destroy(hFeature);
+ }
+ OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+ }
+ }
+ }
+
+ // in the case we cannot handle the native string, go back to the client
+ // side evaluation by unsetting it.
+ if( !bIsOKForSQLCompose && dialect != NULL && layer->filter.native_string )
+ {
+ msDebug("msOGRFileWhichShapes(): unsetting native_string\n");
+ msFree( layer->filter.native_string );
+ layer->filter.native_string = NULL;
+ dialect = NULL;
}
// we'll go strictly two possible ways:
@@ -1841,9 +1909,17 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
} else if (strncmp(dialect, "SQLite", 6) == 0) {
if (filter) filter = msStringConcatenate(filter, " AND");
filter = msStringConcatenate(filter, " ");
- filter = msStringConcatenate(filter, pszTableName);
- filter = msStringConcatenate(filter, ".ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = '");
- filter = msStringConcatenate(filter, pszTableName);
+ filter = msStringConcatenate(filter, pszMainTableName);
+ filter = msStringConcatenate(filter, ".");
+ const char* pszFIDColumn = OGR_L_GetFIDColumn(psInfo->hLayer);
+ if( pszRowId )
+ filter = msStringConcatenate(filter, pszRowId);
+ else if( pszFIDColumn != NULL && pszFIDColumn[0] != '\0' )
+ filter = msStringConcatenate(filter, pszFIDColumn);
+ else
+ filter = msStringConcatenate(filter, "ROWID");
+ filter = msStringConcatenate(filter, " IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = '");
+ filter = msStringConcatenate(filter, pszSpatialFilterTableName);
filter = msStringConcatenate(filter, "' ");
const char* pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer);
if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) {
@@ -1906,7 +1982,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
RELEASE_OGR_LOCK;
msSetError(MS_OGRERR, "ExecuteSQL(%s) failed.\n%s", "msOGRFileWhichShapes()", select, CPLGetLastErrorMsg());
msFree(select);
- msFree(pszTableName);
+ msFree(pszMainTableName);
+ msFree(pszSpatialFilterTableName);
+ msFree(pszRowId);
return MS_FAILURE;
}
@@ -1973,7 +2051,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
msSetError(MS_OGRERR, "SetAttributeFilter(%s) failed on layer %s.\n%s", "msOGRFileWhichShapes()", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
RELEASE_OGR_LOCK;
msFree(pszOGRFilter);
- msFree(pszTableName);
+ msFree(pszMainTableName);
+ msFree(pszSpatialFilterTableName);
+ msFree(pszRowId);
msFree(select);
return MS_FAILURE;
}
@@ -1983,7 +2063,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
}
- msFree(pszTableName);
+ msFree(pszMainTableName);
+ msFree(pszSpatialFilterTableName);
+ msFree(pszRowId);
msFree(select);
/* ------------------------------------------------------------------
Binary file not shown.
@@ -0,0 +1,38 @@
+Content-Type: text/xml; charset=UTF-8
+
+<?xml version='1.0' encoding="UTF-8" ?>
+<wfs:FeatureCollection
+ xmlns:ms="http://mapserver.gis.umn.edu/mapserver"
+ xmlns:wfs="http://www.opengis.net/wfs"
+ xmlns:gml="http://www.opengis.net/gml"
+ xmlns:ogc="http://www.opengis.net/ogc"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd
+ http://mapserver.gis.umn.edu/mapserver http://localhost/path/to/wfs_simple?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=myview&amp;OUTPUTFORMAT=XMLSCHEMA">
+ <gml:boundedBy>
+ <gml:Box srsName="EPSG:32632">
+ <gml:coordinates>643513.360000,4896928.190000 643513.360000,4896928.190000</gml:coordinates>
+ </gml:Box>
+ </gml:boundedBy>
+<!-- WARNING: FeatureId item 'ID' not found in typename 'myview'. -->
+ <gml:featureMember>
+ <ms:myview>
+ <gml:boundedBy>
+ <gml:Box srsName="EPSG:32632">
+ <gml:coordinates>643513.360000,4896928.190000 643513.360000,4896928.190000</gml:coordinates>
+ </gml:Box>
+ </gml:boundedBy>
+ <ms:msGeometry>
+ <gml:Point srsName="EPSG:32632">
+ <gml:coordinates>643513.360000,4896928.190000</gml:coordinates>
+ </gml:Point>
+ </ms:msGeometry>
+ <ms:name>Fanano</ms:name>
+ <ms:peoples>2910</ms:peoples>
+ <ms:localcounc>1</ms:localcounc>
+ <ms:county>0</ms:county>
+ <ms:region>0</ms:region>
+ </ms:myview>
+ </gml:featureMember>
+</wfs:FeatureCollection>
+
@@ -61,6 +61,9 @@
# RUN_PARMS: wfs_ogr_native_sql_30.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><Equals><PropertyName>Geometry</PropertyName><Point srsName="EPSG:32632"><pos>662773 4891987.41</pos></Point></Equals></Filter>" > [RESULT]
# RUN_PARMS: wfs_ogr_native_sql_31.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><Beyond><Distance unit="m">20000</Distance><PropertyName>Geometry</PropertyName><Polygon><exterior><LinearRing><posList>653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103</posList></LinearRing></exterior></Polygon></Beyond></Filter>" > [RESULT]
# RUN_PARMS: wfs_ogr_native_sql_32.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=towns&OUTPUTFORMAT=GML2&FILTER=<Filter><DWithin><Distance unit="m">1000</Distance><PropertyName>Geometry</PropertyName><Polygon><exterior><LinearRing><posList>653627 4881103 653174 4890443 663148 4887813 663330 4879471 653627 4881103</posList></LinearRing></exterior></Polygon></DWithin></Filter>" > [RESULT]
+#
+# Same as wfs_ogr_native_sql_02 on a view
+# RUN_PARMS: wfs_ogr_native_sql_33.xml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=myview&OUTPUTFORMAT=GML2&FILTER=<Filter><AND><BBOX><PropertyName>Geometry</PropertyName><Box srsName='EPSG:32632'><coordinates>643159,4877386 696879,4898059</coordinates></Box></BBOX><PropertyIsEqualTo><PropertyName>name</PropertyName><Literal>Fanano</Literal></PropertyIsEqualTo></AND></Filter>" > [RESULT]
MAP
@@ -118,4 +121,26 @@ LAYER
TEMPLATE "wfs_ogr_native_sql.map"
END # Layer
+LAYER
+ NAME myview
+ DATA myview
+ CONNECTIONTYPE OGR
+ CONNECTION "./data/db.sqlite"
+ PROCESSING "NATIVE_SQL=YES"
+ METADATA
+ "ows_title" "myview"
+ "wfs_featureid" "ID"
+ "gml_include_items" "all"
+ "gml_types" "auto"
+ "wfs_getfeature_formatlist" "ogrgml"
+ END
+ TYPE POINT
+ STATUS ON
+ PROJECTION
+ "init=epsg:32632"
+ END
+
+ TEMPLATE "wfs_ogr_native_sql.map"
+END # Layer
+
END # Map File

1 comment on commit 58ce9c4

@ruhri

This comment has been minimized.

Show comment
Hide comment
@ruhri

ruhri Jul 28, 2016

Hi @rouault ,
I'm not sure whether you read my last three posts in #5218.
If not, pleease could you have a look at them - I think my experiences relate to your changes.

Thank You

ruhri commented on 58ce9c4 Jul 28, 2016

Hi @rouault ,
I'm not sure whether you read my last three posts in #5218.
If not, pleease could you have a look at them - I think my experiences relate to your changes.

Thank You

Please sign in to comment.