[gdal-dev] [Proposed new feature] A '"SQLite" SQL dialect for OGR

Even Rouault even.rouault at mines-paris.org
Sat Aug 18 10:03:56 PDT 2012


Hi folks,

I've attached in 
http://trac.osgeo.org/gdal/attachment/ticket/4782/sqlite_dialect.patch a patch 
that adds a SQLite alternate SQL dialect that can be used with any OGR 
datasource (only available if GDAL/OGR is configured with SQLite support of 
course)

To remind you the concept of SQL dialects, for non-RDBMS OGR drivers, OGR uses 
its own SQL engine, which is the called the OGRSQL dialect. Whereas for RDBMS 
OGR drivers, their own SQL engine will be used, unless otherwise specified.

This patchs adds the capability to use a SQLite dialect (through the -dialect 
option of ogrinfo or ogr2ogr for example). When doing so, the SQLite SQL 
engine is used, and when Spatialite is available, all the Spatialite functions 
( see http://www.gaia-gis.it/gaia-sins/spatialite-sql-3.0.0.html ) can also be 
used.

Technically, this works thanks to a temporary in-memory SQLite DB and a module 
(ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp) that exposes OGR layers to 
SQLite through its Virtual Table mechanism ( http://www.sqlite.org/vtab.html 
). When the datasource you operate on is opened in update mode and that the 
corresponding OGR driver supports CreateFeature()/SetFeature()/DeleteFeature() 
operations, SQL INSERT/UPDATE/DELETE operations will work too.

What do you think about it ?

A few non-exhaustive examples of things you can do :

# Initial CSV file :

$ cat my.csv
id,foo,bar,long,lat
1,"foo","bar",2,49
1,"foo","bar",3,50
2,"foo2","bar2",-2,49
2,"foo2","bar2",-3,51

# Creates a Geometry field from each (long,lat) tuple :

$ ogrinfo my.csv -dialect sqlite -sql "SELECT *, MakePoint(CAST(long AS 
FLOAT), CAST(lat AS FLOAT)) as geometry FROM my" -q

Layer name: SELECT
OGRFeature(SELECT):0
  id (String) = 1
  foo (String) = foo
  bar (String) = bar
  long (String) = 2
  lat (String) = 49
  POINT (2 49)

OGRFeature(SELECT):1
  id (String) = 1
  foo (String) = foo
  bar (String) = bar
  long (String) = 3
  lat (String) = 50
  POINT (3 50)

OGRFeature(SELECT):2
  id (String) = 2
  foo (String) = foo2
  bar (String) = bar2
  long (String) = -2
  lat (String) = 49
  POINT (-2 49)

OGRFeature(SELECT):3
  id (String) = 2
  foo (String) = foo2
  bar (String) = bar2
  long (String) = -3
  lat (String) = 51
  POINT (-3 51)


# Merge all the points that have the same id into a line :

$ ogrinfo my.csv -dialect sqlite -sql "SELECT id, foo,bar, 
MakeLine(MakePoint(CAST(long AS FLOAT), CAST(lat AS FLOAT))) FROM my GROUP BY 
id" -q

Layer name: SELECT
OGRFeature(SELECT):0
  id (String) = 1
  foo (String) = foo
  bar (String) = bar
  LINESTRING (2 49,3 50)

OGRFeature(SELECT):1
  id (String) = 2
  foo (String) = foo2
  bar (String) = bar2
  LINESTRING (-2 49,-3 51)

# Compute the geodesic length of each line :

$ ogrinfo my.csv -dialect sqlite -sql "SELECT id,  
GeodesicLength(SetSRID(MakeLine(MakePoint(CAST(long AS FLOAT), CAST(lat AS 
FLOAT))),4326)) AS total_length FROM my GROUP BY id" -q

Layer name: SELECT
OGRFeature(SELECT):0
  id (String) = 1
  total_length (Real) = 132725.477910869

OGRFeature(SELECT):1
  id (String) = 2
  total_length (Real) = 233720.037020965

# Appends a new entry in the CSV :

$ ogrinfo my.csv -dialect sqlite -sql "insert into my (id,foo,bar,long,lat) 
values (3,'foo3','bar3',2.5,49.5)"

$ cat my.csv
id,foo,bar,long,lat
1,"foo","bar",2,49
1,"foo","bar",3,50
2,"foo2","bar2",-2,49
2,"foo2","bar2",-3,51
3,foo3,bar3,2.5,49.5

# Reprojection from EPSG:32631 to EPSG:4326 :

$ ogrinfo poly.shp -dialect sqlite -sql "SELECT 
ST_Transform(SetSRID(GEOMETRY,32631),4326) AS GEOMETRY, * FROM poly WHERE 
EAS_ID = 170"
INFO: Open of `poly.shp'
      using driver `ESRI Shapefile' successful.

Layer name: SELECT
Geometry: Unknown (any)
Feature Count: 1
Extent: (2.750069, 43.034444) - (2.751428, 43.035184)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]
Geometry Column = GEOMETRY
AREA: Real (0.0)
EAS_ID: Real (0.0)
PRFEDEA: String (0.0)
OGRFeature(SELECT):0
  AREA (Real) = 5268.813
  EAS_ID (Real) = 170
  PRFEDEA (String) = 35043413
  POLYGON ((2.751427625469495 43.034734578878634,2.750298298604006 
43.034443959553869,2.75006933958772 43.03490271631064,2.75124435992688 
43.035184432169061,2.751427625469495 43.034734578878634))

Note: a similar capability was already available in OGR 1.9 for Shapefiles, 
through the use of the VirtualShape module that is embedded in Spatialite. See 
the http://gdal.org/ogr/drv_sqlite.html page.

Best regards,

Even



More information about the gdal-dev mailing list